Skip to content

Commit

Permalink
chore: use sealed interfaces and objects for all key tokens (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
florentmaitre authored Nov 26, 2024
1 parent 35055c1 commit 0e1b5b0
Show file tree
Hide file tree
Showing 23 changed files with 615 additions and 559 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/com/orange/ouds/app/ui/TopBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private fun TopBar(
text = title,
color = OudsColorKeyToken.Content.Default.value,
modifier = Modifier.semantics { traversalIndex = -1f },
style = OudsTypographyKeyToken.HeadingMedium.value
style = OudsTypographyKeyToken.Heading.Medium.value
)
},
actions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory<*>, onSubcategoryClic
text = stringResource(id = subcategory.nameRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = OudsTypographyKeyToken.HeadingMedium.value
style = OudsTypographyKeyToken.Heading.Medium.value
)
}
}
Expand All @@ -89,7 +89,7 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory<*>, onSubcategoryClic
text = stringResource(id = tokenProperty.nameRes),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = OudsTypographyKeyToken.HeadingMedium.value
style = OudsTypographyKeyToken.Heading.Medium.value
)
}

Expand All @@ -113,7 +113,7 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory<*>, onSubcategoryClic
text = stringResource(id = R.string.app_tokens_dimension_size_iconWithTextTokenName_label, token.name, token.literalValue),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = OudsTypographyKeyToken.BodyDefaultMedium.value,
style = OudsTypographyKeyToken.Body.Default.Medium.value,
color = OudsColorKeyToken.Content.Muted.value
)
}
Expand All @@ -135,15 +135,15 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory<*>, onSubcategoryClic
style = if (tokenProperty == TokenProperty.Typography) {
token.value as TextStyle
} else {
OudsTypographyKeyToken.BodyStrongLarge.value
OudsTypographyKeyToken.Body.Strong.Large.value
}
)
Text(
modifier = Modifier.fillMaxWidth(),
text = token.literalValue,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = OudsTypographyKeyToken.BodyDefaultMedium.value.copy(color = OudsColorKeyToken.Content.Muted.value)
style = OudsTypographyKeyToken.Body.Default.Medium.value.copy(color = OudsColorKeyToken.Content.Muted.value)
)
}
}
Expand Down
108 changes: 50 additions & 58 deletions app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ package com.orange.ouds.app.ui.tokens
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import com.orange.ouds.app.R
import com.orange.ouds.core.theme.value
import com.orange.ouds.app.ui.utilities.getTokenName
import com.orange.ouds.app.ui.utilities.getTokens
import com.orange.ouds.theme.tokens.OudsBorderKeyToken
import com.orange.ouds.theme.tokens.OudsColorKeyToken
import com.orange.ouds.theme.tokens.OudsElevationKeyToken
Expand All @@ -34,213 +35,204 @@ sealed class TokenProperty<T>(

data object BorderRadius : TokenProperty<TokenCategory.Border>(
nameRes = R.string.app_tokens_border_radius_label,
tokens = { OudsBorderKeyToken.Radius.entries.map { Token(it.name, it.value) } },
tokens = { OudsBorderKeyToken.Radius::class.getTokens() },
categoryClass = TokenCategory.Border::class
)

data object BorderStyle : TokenProperty<TokenCategory.Border>(
nameRes = R.string.app_tokens_border_style_label,
tokens = { OudsBorderKeyToken.Style.entries.map { Token(it.name, it.value) } },
tokens = { OudsBorderKeyToken.Style::class.getTokens() },
categoryClass = TokenCategory.Border::class
)

data object BorderWidth : TokenProperty<TokenCategory.Border>(
nameRes = R.string.app_tokens_border_width_label,
tokens = { OudsBorderKeyToken.Width.entries.map { Token(it.name, it.value) } },
tokens = { OudsBorderKeyToken.Width::class.getTokens() },
categoryClass = TokenCategory.Border::class
)

data object ColorAction : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_action_label,
tokens = { OudsColorKeyToken.Action::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Action::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorAlways : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_always_label,
tokens = { OudsColorKeyToken.Always::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Always::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorBackground : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_background_label,
tokens = { OudsColorKeyToken.Background::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Background::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorBorder : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_border_label,
tokens = { OudsColorKeyToken.Border::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Border::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorBrand : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_brand_label,
tokens = { OudsColorKeyToken.Brand::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Brand::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorContent : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_content_label,
tokens = { OudsColorKeyToken.Content::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Content::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorDecorative : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_decorative_label,
tokens = { OudsColorKeyToken.Decorative::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Decorative::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorElevation : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_elevation_label,
tokens = { OudsColorKeyToken.Elevation::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Elevation::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object ColorGradient : TokenProperty<TokenCategory.Color>(
nameRes = R.string.app_tokens_color_gradient_label,
tokens = { OudsColorKeyToken.Gradient::class.getTokens<OudsColorKeyToken>() },
tokens = { OudsColorKeyToken.Gradient::class.getTokens() },
categoryClass = TokenCategory.Color::class
)

data object Elevation : TokenProperty<TokenCategory.Elevation>(
nameRes = null,
tokens = { OudsElevationKeyToken.entries.map { Token(it.name, it.value) } },
tokens = { OudsElevationKeyToken::class.getTokens() },
categoryClass = TokenCategory.Elevation::class
)

data object Grid : TokenProperty<TokenCategory.Grid>(
nameRes = null,
tokens = { OudsGridKeyToken.entries.map { Token(it.name, it.value) } },
tokens = { OudsGridKeyToken::class.getTokens() },
categoryClass = TokenCategory.Grid::class
)

data object Opacity : TokenProperty<TokenCategory.Opacity>(
nameRes = null,
tokens = { OudsOpacityKeyToken.entries.map { Token(it.name, it.value) } },
tokens = { OudsOpacityKeyToken::class.getTokens() },
categoryClass = TokenCategory.Opacity::class
)

data object SizeIconDecorative : TokenProperty<TokenCategory.Dimension.Size>(
nameRes = R.string.app_tokens_dimension_size_iconDecorative_label,
tokens = { OudsSizeKeyToken.IconDecorative.entries.map { Token(it.name, it.value) } },
tokens = { OudsSizeKeyToken.Icon.Decorative::class.getTokens() },
categoryClass = TokenCategory.Dimension.Size::class
)

data object SizeIconWithText : TokenProperty<TokenCategory.Dimension.Size>(
nameRes = R.string.app_tokens_dimension_size_iconWithText_label,
tokens = { OudsSizeKeyToken.IconWithText.entries.map { Token(it.name, it.value) } },
tokens = {
val keyTokenClasses = listOf(
OudsSizeKeyToken.Icon.WithHeadingExtraLarge::class,
OudsSizeKeyToken.Icon.WithHeadingLarge::class,
OudsSizeKeyToken.Icon.WithHeadingMedium::class,
OudsSizeKeyToken.Icon.WithHeadingSmall::class,
OudsSizeKeyToken.Icon.WithBodyLarge::class,
OudsSizeKeyToken.Icon.WithBodyMedium::class,
OudsSizeKeyToken.Icon.WithBodySmall::class,
OudsSizeKeyToken.Icon.WithLabelExtraLarge::class,
OudsSizeKeyToken.Icon.WithLabelLarge::class,
OudsSizeKeyToken.Icon.WithLabelMedium::class,
OudsSizeKeyToken.Icon.WithLabelSmall::class,
)
keyTokenClasses.flatMap { keyTokenClass ->
keyTokenClass.getTokens(tokenName = { it.getTokenName(OudsSizeKeyToken.Icon::class).removePrefix("With") })
}
},
categoryClass = TokenCategory.Dimension.Size::class
)

data object SpaceColumnGap : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_columnGap_label,
tokens = { OudsSpaceKeyToken.ColumnGap.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.ColumnGap::class.getTokens(recursive = false) },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceColumnGapWithIcon : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_columnGapWithIcon_label,
tokens = { OudsSpaceKeyToken.ColumnGap.WithIcon.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.ColumnGap.WithIcon::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceColumnGapWithArrow : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_columnGapWithArrow_label,
tokens = { OudsSpaceKeyToken.ColumnGap.WithArrow.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.ColumnGap.WithArrow::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceFixed : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_fixed_label,
tokens = { OudsSpaceKeyToken.Fixed.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.Fixed::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingInline : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingInline_label,
tokens = { OudsSpaceKeyToken.PaddingInline.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.PaddingInline::class.getTokens(recursive = false) },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingInlineWithIcon : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingInlineWithIcon_label,
tokens = { OudsSpaceKeyToken.PaddingInline.WithIcon.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.PaddingInline.WithIcon::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingInlineWithArrow : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingInlineWithArrow_label,
tokens = { OudsSpaceKeyToken.PaddingInline.WithArrow.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.PaddingInline.WithArrow::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingInset : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingInset_label,
tokens = { OudsSpaceKeyToken.Inset.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.Inset::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingStack : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingStack_label,
tokens = { OudsSpaceKeyToken.PaddingBlock.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.PaddingBlock::class.getTokens(recursive = false) },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpacePaddingStackWithIcon : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_paddingStackWithIcon_label,
tokens = { OudsSpaceKeyToken.PaddingBlock.WithIcon.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.PaddingBlock.WithIcon::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceRowGap : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_rowGap_label,
tokens = { OudsSpaceKeyToken.RowGap.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.RowGap::class.getTokens(recursive = false) },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceRowGapWithIcon : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_rowGapWithIcon_label,
tokens = { OudsSpaceKeyToken.RowGap.WithIcon.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.RowGap.WithIcon::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object SpaceScaled : TokenProperty<TokenCategory.Dimension.Space>(
nameRes = R.string.app_tokens_dimension_space_scaled_label,
tokens = { OudsSpaceKeyToken.Scaled.entries.map { Token(it.name, it.value) } },
tokens = { OudsSpaceKeyToken.Scaled::class.getTokens() },
categoryClass = TokenCategory.Dimension.Space::class
)

data object Typography : TokenProperty<TokenCategory.Typography>(
nameRes = null,
tokens = { OudsTypographyKeyToken.entries.map { Token(it.name, it.value) } },
tokens = { OudsTypographyKeyToken::class.getTokens() },
categoryClass = TokenCategory.Typography::class
)
}

@PublishedApi
internal fun KClass<*>.getRelativeName(parent: KClass<*>): String {
return qualifiedName.orEmpty().removePrefix("${parent.qualifiedName.orEmpty()}.")
}

@PublishedApi
internal inline fun <reified T> KClass<*>.getNestedObjects(): List<T> {
return getNestedClassesRecursive().mapNotNull { it.objectInstance }.filterIsInstance<T>()
}

@PublishedApi
internal fun KClass<*>.getNestedClassesRecursive(): List<KClass<*>> {
return nestedClasses + nestedClasses.flatMap { it.getNestedClassesRecursive() }
}

@Composable
inline fun <reified T : Any> KClass<*>.getTokens(): List<Token<*>> {
return getNestedObjects<T>().mapNotNull { keyToken ->
val value = when (keyToken) {
is OudsColorKeyToken -> keyToken.value
else -> null
}
value?.let { Token(keyToken::class.getRelativeName(this).removeSuffix(".Companion"), it) }
}.sortedBy { it.name }
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private fun SpaceHeaderText(spaceTokenProperty: TokenProperty<TokenCategory.Dime
modifier = modifier.background(color = OudsColorKeyToken.Background.Emphasized.value),
text = stringResource(id = textResId),
color = OudsColorKeyToken.Content.Default.OnBgEmphasized.value,
style = OudsTypographyKeyToken.BodyDefaultMedium.value
style = OudsTypographyKeyToken.Body.Default.Medium.value
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.orange.ouds.app.R
import com.orange.ouds.app.ui.utilities.getTokens
import com.orange.ouds.core.theme.value
import com.orange.ouds.foundation.extensions.asOrNull
import com.orange.ouds.foundation.extensions.orElse
import com.orange.ouds.theme.OudsBorderStyle
import com.orange.ouds.theme.dashedBorder
Expand Down Expand Up @@ -125,7 +128,6 @@ fun SizeIconDecorativeIllustrationBox(size: Dp) {

@Composable
fun SizeIconWithTextIllustrationRow(size: Dp, tokenName: String) {
val label = tokenName.substringBefore("Size")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(OudsSpaceKeyToken.Fixed.Shorter.value),
Expand All @@ -137,12 +139,19 @@ fun SizeIconWithTextIllustrationRow(size: Dp, tokenName: String) {
tint = Color(0xFF26B2FF), //TODO use AlwaysInfo token when available
contentDescription = null
)
val style = OudsTypographyKeyToken::class.getTokens()
.asOrNull<List<Token<TextStyle>>>()
?.firstOrNull { typographyToken ->
tokenName.split(".").firstOrNull() == typographyToken.name.replace("Strong", "").replace(".", "")
}
?.value
.orElse { LocalTextStyle.current }
Text(
modifier = Modifier.weight(1f),
text = label,
text = tokenName,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = OudsTypographyKeyToken.entries.firstOrNull { it.name.replace("Strong", "") == label }?.value.orElse { LocalTextStyle.current }
style = style
)
}
}
Expand Down
Loading

0 comments on commit 0e1b5b0

Please sign in to comment.