diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt index c2c6ecb4..b3c3cf77 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt @@ -20,13 +20,13 @@ import com.orange.ouds.app.R val tokenCategories = TokenCategory::class.sealedSubclasses.mapNotNull { it.objectInstance } @Immutable -sealed class TokenCategory( +sealed class TokenCategory( @StringRes val nameRes: Int, @DrawableRes val imageRes: Int, @StringRes val descriptionRes: Int, - val properties: List = emptyList(), - val subcategories: List = emptyList(), -) { + val properties: List> = emptyList(), + val subcategories: List> = emptyList(), +) where T : TokenCategory { companion object { fun fromId(tokenId: Long) = tokenCategories.firstOrNull { token -> token.id == tokenId } @@ -36,14 +36,14 @@ sealed class TokenCategory( val isSubcategory: Boolean get() = tokenCategories.any { it.subcategories.contains(this) } - data object Border : TokenCategory( + data object Border : TokenCategory( R.string.app_tokens_border_label, R.drawable.ic_border, R.string.app_tokens_border_description_text, listOf(TokenProperty.BorderWidth, TokenProperty.BorderRadius, TokenProperty.BorderStyle) ) - data object Color : TokenCategory( + data object Color : TokenCategory( R.string.app_tokens_color_label, R.drawable.ic_palette, R.string.app_tokens_color_description_text, @@ -60,13 +60,13 @@ sealed class TokenCategory( ) ) - data object Dimension : TokenCategory( + data object Dimension : TokenCategory( R.string.app_tokens_dimension_label, R.drawable.ic_dimension, R.string.app_tokens_dimension_description_text, subcategories = listOf(Space, Size) ) { - data object Space : TokenCategory( + data object Space : TokenCategory( R.string.app_tokens_dimension_space_label, R.drawable.ic_dimension, R.string.app_tokens_dimension_space_description_text, @@ -87,7 +87,7 @@ sealed class TokenCategory( ), ) - data object Size : TokenCategory( + data object Size : TokenCategory( R.string.app_tokens_dimension_size_label, R.drawable.ic_dimension, R.string.app_tokens_dimension_size_description_text, @@ -95,28 +95,28 @@ sealed class TokenCategory( ) } - data object Elevation : TokenCategory( + data object Elevation : TokenCategory( R.string.app_tokens_elevation_label, R.drawable.ic_layers, R.string.app_tokens_elevation_description_text, listOf(TokenProperty.Elevation) ) - data object Grid : TokenCategory( + data object Grid : TokenCategory( R.string.app_tokens_grid_label, R.drawable.ic_menu_grid, R.string.app_tokens_grid_description_text, listOf(TokenProperty.Grid) ) - data object Opacity : TokenCategory( + data object Opacity : TokenCategory( R.string.app_tokens_opacity_label, R.drawable.ic_filter_effects, R.string.app_tokens_opacity_description_text, listOf(TokenProperty.Opacity) ) - data object Typography : TokenCategory( + data object Typography : TokenCategory( R.string.app_tokens_typography_label, R.drawable.ic_typography, R.string.app_tokens_typography_description_text, diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategoryDetailScreen.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategoryDetailScreen.kt index 03ac31c5..6e5db5e8 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategoryDetailScreen.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategoryDetailScreen.kt @@ -47,7 +47,7 @@ import com.orange.ouds.theme.tokens.OudsSpaceKeyToken import com.orange.ouds.theme.tokens.OudsTypographyKeyToken @Composable -fun TokenCategoryDetailScreen(tokenCategory: TokenCategory, onSubcategoryClick: (Long) -> Unit) { +fun TokenCategoryDetailScreen(tokenCategory: TokenCategory<*>, onSubcategoryClick: (Long) -> Unit) { Screen { LazyColumn(contentPadding = PaddingValues(bottom = OudsSpaceKeyToken.Fixed.Medium.value)) { @@ -56,10 +56,6 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory, onSubcategoryClick: descriptionRes = tokenCategory.descriptionRes, imageRes = tokenCategory.imageRes ) - - if (tokenCategory == TokenCategory.Grid) { - GridIllustrations() - } } if (tokenCategory.subcategories.isNotEmpty()) { @@ -89,7 +85,7 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory, onSubcategoryClick: Text( modifier = Modifier .fillMaxWidth() - .padding(OudsSpaceKeyToken.Fixed.Medium.value), + .padding(all = OudsSpaceKeyToken.Fixed.Medium.value), text = stringResource(id = tokenProperty.nameRes), maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -97,6 +93,13 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory, onSubcategoryClick: ) } + TokenPropertyHeader( + modifier = Modifier + .padding(horizontal = OudsSpaceKeyToken.Fixed.Medium.value) + .padding(bottom = OudsSpaceKeyToken.Fixed.Medium.value), + tokenProperty = tokenProperty + ) + tokenProperty.tokens().forEach { token -> if (tokenProperty == TokenProperty.SizeIconWithText) { Column( @@ -153,17 +156,17 @@ fun TokenCategoryDetailScreen(tokenCategory: TokenCategory, onSubcategoryClick: } @Composable -private fun TokenIllustration(tokenProperty: TokenProperty, token: Token) = when (tokenProperty) { - TokenProperty.BorderWidth -> BorderIllustrationBox(width = token.value as Dp) - TokenProperty.BorderRadius -> BorderIllustrationBox(shape = RoundedCornerShape(token.value as Dp)) - TokenProperty.BorderStyle -> BorderIllustrationBox(style = token.value as OudsBorderStyle) - TokenProperty.ColorAction, TokenProperty.ColorAlways, TokenProperty.ColorBackground, TokenProperty.ColorBorder, TokenProperty.ColorBrand, TokenProperty.ColorContent, +private fun TokenIllustration(tokenProperty: TokenProperty<*>, token: Token) = when (tokenProperty) { + is TokenProperty.BorderWidth -> BorderIllustrationBox(width = token.value as Dp) + is TokenProperty.BorderRadius -> BorderIllustrationBox(shape = RoundedCornerShape(token.value as Dp)) + is TokenProperty.BorderStyle -> BorderIllustrationBox(style = token.value as OudsBorderStyle) + is TokenProperty.ColorAction, TokenProperty.ColorAlways, TokenProperty.ColorBackground, TokenProperty.ColorBorder, TokenProperty.ColorBrand, TokenProperty.ColorContent, TokenProperty.ColorElevation, TokenProperty.ColorGradient, TokenProperty.ColorDecorative -> BorderIllustrationBox(backgroundColor = token.value as Color) - TokenProperty.Opacity -> OpacityIllustrationBox(opacity = token.value as Float) - TokenProperty.Elevation -> ElevationIllustrationSurface(elevation = token.value as Dp) - TokenProperty.SizeIconDecorative -> SizeIconDecorativeIllustrationBox(size = token.value as Dp) - TokenProperty.SizeIconWithText -> SizeIconWithTextIllustrationRow(size = token.value as Dp, token.name) - TokenProperty.SpaceColumnGap, TokenProperty.SpaceFixed, TokenProperty.SpaceScaled -> SpaceIllustrationBox( + is TokenProperty.Opacity -> OpacityIllustrationBox(opacity = token.value as Float) + is TokenProperty.Elevation -> ElevationIllustrationSurface(elevation = token.value as Dp) + is TokenProperty.SizeIconDecorative -> SizeIconDecorativeIllustrationBox(size = token.value as Dp) + is TokenProperty.SizeIconWithText -> SizeIconWithTextIllustrationRow(size = token.value as Dp, token.name) + is TokenProperty.SpaceColumnGap, TokenProperty.SpaceFixed, TokenProperty.SpaceScaled -> SpaceIllustrationBox( size = token.value as Dp, contentAlignment = Alignment.Center ) @@ -178,19 +181,38 @@ private fun TokenIllustration(tokenProperty: TokenProperty, token: Token) = TokenProperty.Typography, TokenProperty.Grid -> Unit } +@Composable +private fun TokenPropertyHeader(tokenProperty: TokenProperty<*>, modifier: Modifier = Modifier) { + @Suppress("UNCHECKED_CAST") + when (tokenProperty.categoryClass) { + TokenCategory.Grid::class -> GridHeader(modifier = modifier) + TokenCategory.Dimension.Space::class -> SpaceHeader( + modifier = modifier, + spaceTokenProperty = tokenProperty as TokenProperty + ) + else -> {} + } +} + @UiModePreviews.Default @Composable private fun PreviewTokenCategoryDetailScreen( - @PreviewParameter(TokenCategoryDetailScreenPreviewParameterProvider::class) parameter: TokenCategory + @PreviewParameter(TokenCategoryDetailScreenPreviewParameterProvider::class) parameter: TokenCategory<*> ) = OudsPreview { TokenCategoryDetailScreen(parameter) {} } -private class TokenCategoryDetailScreenPreviewParameterProvider : BasicPreviewParameterProvider(*previewParameterValues.toTypedArray()) +private class TokenCategoryDetailScreenPreviewParameterProvider : BasicPreviewParameterProvider>(*previewParameterValues.toTypedArray()) -private val previewParameterValues: List +private val previewParameterValues: List> get() = listOf( - TokenCategory.Opacity, - TokenCategory.Elevation, - TokenCategory.Grid + TokenCategory.Border, +// TokenCategory.Color, +// TokenCategory.Dimension, +// TokenCategory.Dimension.Size, +// TokenCategory.Dimension.Space, +// TokenCategory.Elevation, +// TokenCategory.Grid, +// TokenCategory.Opacity, +// TokenCategory.Typography, ) \ No newline at end of file diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt index f3527586..cbc08f09 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt @@ -24,160 +24,197 @@ import com.orange.ouds.theme.tokens.OudsOpacityKeyToken import com.orange.ouds.theme.tokens.OudsSizeKeyToken import com.orange.ouds.theme.tokens.OudsSpaceKeyToken import com.orange.ouds.theme.tokens.OudsTypographyKeyToken +import kotlin.reflect.KClass -sealed class TokenProperty( +sealed class TokenProperty( @StringRes val nameRes: Int?, - val tokens: @Composable () -> List> -) { - data object BorderRadius : TokenProperty( + val tokens: @Composable () -> List>, + val categoryClass: KClass +) where T : TokenCategory { + + data object BorderRadius : TokenProperty( nameRes = R.string.app_tokens_border_radius_label, - tokens = { OudsBorderKeyToken.Radius.entries.map { Token(it.name, it.value) } } + tokens = { OudsBorderKeyToken.Radius.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Border::class ) - data object BorderStyle : TokenProperty( + data object BorderStyle : TokenProperty( nameRes = R.string.app_tokens_border_style_label, - tokens = { OudsBorderKeyToken.Style.entries.map { Token(it.name, it.value) } } + tokens = { OudsBorderKeyToken.Style.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Border::class ) - data object BorderWidth : TokenProperty( + data object BorderWidth : TokenProperty( nameRes = R.string.app_tokens_border_width_label, - tokens = { OudsBorderKeyToken.Width.entries.map { Token(it.name, it.value) } } + tokens = { OudsBorderKeyToken.Width.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Border::class ) - data object ColorAction : TokenProperty( + data object ColorAction : TokenProperty( nameRes = R.string.app_tokens_color_action_label, - tokens = { OudsColorKeyToken.Action.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Action.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorAlways : TokenProperty( + data object ColorAlways : TokenProperty( nameRes = R.string.app_tokens_color_always_label, - tokens = { OudsColorKeyToken.Always.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Always.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorBackground : TokenProperty( + data object ColorBackground : TokenProperty( nameRes = R.string.app_tokens_color_background_label, - tokens = { OudsColorKeyToken.Background.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Background.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorBorder : TokenProperty( + data object ColorBorder : TokenProperty( nameRes = R.string.app_tokens_color_border_label, - tokens = { OudsColorKeyToken.Border.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Border.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorBrand : TokenProperty( + data object ColorBrand : TokenProperty( nameRes = R.string.app_tokens_color_brand_label, - tokens = { OudsColorKeyToken.Brand.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Brand.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorContent : TokenProperty( + data object ColorContent : TokenProperty( nameRes = R.string.app_tokens_color_content_label, - tokens = { OudsColorKeyToken.Content.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Content.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorElevation : TokenProperty( + data object ColorElevation : TokenProperty( nameRes = R.string.app_tokens_color_elevation_label, - tokens = { OudsColorKeyToken.Elevation.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Elevation.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorGradient : TokenProperty( + data object ColorGradient : TokenProperty( nameRes = R.string.app_tokens_color_gradient_label, - tokens = { OudsColorKeyToken.Gradient.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Gradient.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object ColorDecorative : TokenProperty( + data object ColorDecorative : TokenProperty( nameRes = R.string.app_tokens_color_decorative_label, - tokens = { OudsColorKeyToken.Decorative.entries.map { Token(it.name, it.value) } } + tokens = { OudsColorKeyToken.Decorative.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Color::class ) - data object Elevation : TokenProperty( + data object Elevation : TokenProperty( nameRes = null, - tokens = { OudsElevationKeyToken.entries.map { Token(it.name, it.value) } } + tokens = { OudsElevationKeyToken.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Elevation::class ) - data object Grid : TokenProperty( + data object Grid : TokenProperty( nameRes = null, - tokens = { OudsGridKeyToken.entries.map { Token(it.name, it.value) } } + tokens = { OudsGridKeyToken.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Grid::class ) - data object Opacity : TokenProperty( + data object Opacity : TokenProperty( nameRes = null, - tokens = { OudsOpacityKeyToken.entries.map { Token(it.name, it.value) } } + tokens = { OudsOpacityKeyToken.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Opacity::class ) - data object SizeIconDecorative : TokenProperty( + data object SizeIconDecorative : TokenProperty( nameRes = R.string.app_tokens_dimension_size_iconDecorative_label, - tokens = { OudsSizeKeyToken.IconDecorative.entries.map { Token(it.name, it.value) } } + tokens = { OudsSizeKeyToken.IconDecorative.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Size::class ) - data object SizeIconWithText : TokenProperty( + data object SizeIconWithText : TokenProperty( nameRes = R.string.app_tokens_dimension_size_iconWithText_label, - tokens = { OudsSizeKeyToken.IconWithText.entries.map { Token(it.name, it.value) } } + tokens = { OudsSizeKeyToken.IconWithText.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Size::class ) - data object SpaceColumnGap : TokenProperty( + data object SpaceColumnGap : TokenProperty( nameRes = R.string.app_tokens_dimension_space_columnGap_label, - tokens = { OudsSpaceKeyToken.ColumnGap.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.ColumnGap.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceColumnGapWithIcon : TokenProperty( + data object SpaceColumnGapWithIcon : TokenProperty( nameRes = R.string.app_tokens_dimension_space_columnGapWithIcon_label, - tokens = { OudsSpaceKeyToken.ColumnGap.WithIcon.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.ColumnGap.WithIcon.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceColumnGapWithArrow : TokenProperty( + data object SpaceColumnGapWithArrow : TokenProperty( nameRes = R.string.app_tokens_dimension_space_columnGapWithArrow_label, - tokens = { OudsSpaceKeyToken.ColumnGap.WithArrow.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.ColumnGap.WithArrow.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceFixed : TokenProperty( + data object SpaceFixed : TokenProperty( nameRes = R.string.app_tokens_dimension_space_fixed_label, - tokens = { OudsSpaceKeyToken.Fixed.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.Fixed.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingInline : TokenProperty( + data object SpacePaddingInline : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInline_label, - tokens = { OudsSpaceKeyToken.PaddingInline.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.PaddingInline.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingInlineWithIcon : TokenProperty( + data object SpacePaddingInlineWithIcon : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInlineWithIcon_label, - tokens = { OudsSpaceKeyToken.PaddingInline.WithIcon.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.PaddingInline.WithIcon.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingInlineWithArrow : TokenProperty( + data object SpacePaddingInlineWithArrow : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInlineWithArrow_label, - tokens = { OudsSpaceKeyToken.PaddingInline.WithArrow.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.PaddingInline.WithArrow.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingInset : TokenProperty( + data object SpacePaddingInset : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInset_label, - tokens = { OudsSpaceKeyToken.Inset.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.Inset.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingStack : TokenProperty( + data object SpacePaddingStack : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingStack_label, - tokens = { OudsSpaceKeyToken.PaddingBlock.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.PaddingBlock.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpacePaddingStackWithIcon : TokenProperty( + data object SpacePaddingStackWithIcon : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingStackWithIcon_label, - tokens = { OudsSpaceKeyToken.PaddingBlock.WithIcon.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.PaddingBlock.WithIcon.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceRowGap : TokenProperty( + data object SpaceRowGap : TokenProperty( nameRes = R.string.app_tokens_dimension_space_rowGap_label, - tokens = { OudsSpaceKeyToken.RowGap.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.RowGap.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceRowGapWithIcon : TokenProperty( + data object SpaceRowGapWithIcon : TokenProperty( nameRes = R.string.app_tokens_dimension_space_rowGapWithIcon_label, - tokens = { OudsSpaceKeyToken.RowGap.WithIcon.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.RowGap.WithIcon.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object SpaceScaled : TokenProperty( + data object SpaceScaled : TokenProperty( nameRes = R.string.app_tokens_dimension_space_scaled_label, - tokens = { OudsSpaceKeyToken.Scaled.entries.map { Token(it.name, it.value) } } + tokens = { OudsSpaceKeyToken.Scaled.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Dimension.Space::class ) - data object Typography : TokenProperty(nameRes = null, tokens = { OudsTypographyKeyToken.entries.map { Token(it.name, it.value) } }) + data object Typography : TokenProperty( + nameRes = null, + tokens = { OudsTypographyKeyToken.entries.map { Token(it.name, it.value) } }, + categoryClass = TokenCategory.Typography::class + ) } \ No newline at end of file diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyHeader.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyHeader.kt new file mode 100644 index 00000000..bdc26284 --- /dev/null +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyHeader.kt @@ -0,0 +1,257 @@ +/* + * Software Name: OUDS Android + * SPDX-FileCopyrightText: Copyright (c) Orange SA + * SPDX-License-Identifier: MIT + * + * This software is distributed under the MIT license, + * the text of which is available at https://opensource.org/license/MIT/ + * or see the "LICENSE" file for more details. + * + * Software description: Android library of reusable graphical components + */ + +package com.orange.ouds.app.ui.tokens + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import com.orange.ouds.app.R +import com.orange.ouds.core.theme.value +import com.orange.ouds.core.utilities.OudsPreview +import com.orange.ouds.foundation.utilities.BasicPreviewParameterProvider +import com.orange.ouds.foundation.utilities.UiModePreviews +import com.orange.ouds.theme.dashedBorder +import com.orange.ouds.theme.tokens.OudsColorKeyToken +import com.orange.ouds.theme.tokens.OudsSpaceKeyToken +import com.orange.ouds.theme.tokens.OudsTypographyKeyToken + +@Composable +fun GridHeader(modifier: Modifier = Modifier) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(OudsSpaceKeyToken.Fixed.Medium.value) + ) { + val resourceIds = listOf( + R.drawable.il_tokens_grid_column_margin, + R.drawable.il_tokens_grid_min_width, + R.drawable.il_tokens_grid_max_width + ) + resourceIds.forEach { resourceId -> + Image( + modifier = Modifier + .fillMaxWidth() + .background(OudsColorKeyToken.Background.Emphasized.value), + painter = painterResource(id = resourceId), + contentDescription = null + ) + } + } +} + +@Composable +fun SpaceHeader( + spaceTokenProperty: TokenProperty, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .background(color = OudsColorKeyToken.Background.Emphasized.value) + .padding(all = OudsSpaceKeyToken.Fixed.Medium.value) + ) { + SpaceHeaderContent(spaceTokenProperty = spaceTokenProperty) + } +} + +@Composable +private fun SpaceHeaderContent(spaceTokenProperty: TokenProperty) { + val dashedBorderWidth = 1.dp + + val externalSpaceValues = when (spaceTokenProperty) { + TokenProperty.SpaceScaled -> PaddingValues(start = OudsSpaceKeyToken.Fixed.Shorter.value, top = OudsSpaceKeyToken.Fixed.Shortest.value) + TokenProperty.SpaceFixed, + TokenProperty.SpacePaddingInlineWithArrow, + TokenProperty.SpacePaddingInlineWithIcon -> PaddingValues(start = OudsSpaceKeyToken.Fixed.Shorter.value) + TokenProperty.SpacePaddingInline -> PaddingValues(horizontal = OudsSpaceKeyToken.Fixed.Shorter.value) + TokenProperty.SpacePaddingStack -> PaddingValues(vertical = OudsSpaceKeyToken.Fixed.Shorter.value) + TokenProperty.SpacePaddingStackWithIcon -> PaddingValues(top = OudsSpaceKeyToken.Fixed.Shorter.value) + TokenProperty.SpacePaddingInset -> PaddingValues(all = OudsSpaceKeyToken.Fixed.Shorter.value) + else -> PaddingValues(all = 0.dp) + } + + val internalSpaceColor = when (spaceTokenProperty) { + TokenProperty.SpaceColumnGap, + TokenProperty.SpaceColumnGapWithIcon, + TokenProperty.SpaceColumnGapWithArrow, + TokenProperty.SpaceRowGap, + TokenProperty.SpaceRowGapWithIcon -> OudsColorKeyToken.Always.Info.value + else -> OudsColorKeyToken.Background.Emphasized.value + } + + val modifier = Modifier + .dashedBorder(width = dashedBorderWidth, color = OudsColorKeyToken.Content.DefaultOnBgEmphasized.value) + .padding(all = dashedBorderWidth) + .background(color = OudsColorKeyToken.Always.Info.value) + .padding(externalSpaceValues) + .background(internalSpaceColor) + + val column = remember { + spaceTokenProperty in listOf( + TokenProperty.SpaceRowGap, + TokenProperty.SpaceRowGapWithIcon, + TokenProperty.SpacePaddingStack, + TokenProperty.SpacePaddingStackWithIcon + ) + } + + val arrangement = Arrangement.spacedBy(OudsSpaceKeyToken.Fixed.Shorter.value) + + if (column) { + Column( + modifier = modifier, + verticalArrangement = arrangement + ) { + if (spaceTokenProperty == TokenProperty.SpaceRowGap) { + SpaceHeaderText(spaceTokenProperty = spaceTokenProperty) + } else { + SpaceHeaderImage( + modifier = Modifier.fillMaxWidth(), + spaceTokenProperty = spaceTokenProperty, + alignment = Alignment.CenterStart + ) + } + SpaceHeaderText(spaceTokenProperty = spaceTokenProperty) + } + } else { + Row( + modifier = modifier.height(IntrinsicSize.Min), + horizontalArrangement = arrangement + ) { + if (spaceTokenProperty == TokenProperty.SpaceColumnGap) { + SpaceHeaderText(modifier = Modifier.weight(0.5f), spaceTokenProperty = spaceTokenProperty) + SpaceHeaderText(modifier = Modifier.weight(0.5f), spaceTokenProperty = spaceTokenProperty) + } else { + SpaceHeaderImage( + modifier = Modifier.fillMaxHeight(), + spaceTokenProperty = spaceTokenProperty + ) + SpaceHeaderText(spaceTokenProperty = spaceTokenProperty) + } + } + } +} + +@Composable +private fun SpaceHeaderText(spaceTokenProperty: TokenProperty, modifier: Modifier = Modifier) { + val textResId = when (spaceTokenProperty) { + TokenProperty.SpaceColumnGap -> R.string.app_tokens_dimension_space_columnGapHeader_text + TokenProperty.SpaceColumnGapWithArrow -> R.string.app_tokens_dimension_space_columnGapWithArrowHeader_text + TokenProperty.SpaceColumnGapWithIcon -> R.string.app_tokens_dimension_space_columnGapWithIconHeader_text + TokenProperty.SpaceFixed -> R.string.app_tokens_dimension_space_fixedHeader_text + TokenProperty.SpacePaddingInline -> R.string.app_tokens_dimension_space_paddingInlineHeader_text + TokenProperty.SpacePaddingInlineWithArrow -> R.string.app_tokens_dimension_space_paddingInlineWithArrowHeader_text + TokenProperty.SpacePaddingInlineWithIcon -> R.string.app_tokens_dimension_space_paddingInlineWithIconHeader_text + TokenProperty.SpacePaddingInset -> R.string.app_tokens_dimension_space_paddingInsetHeader_text + TokenProperty.SpacePaddingStack -> R.string.app_tokens_dimension_space_paddingStackHeader_text + TokenProperty.SpacePaddingStackWithIcon -> R.string.app_tokens_dimension_space_paddingStackWithIconHeader_text + TokenProperty.SpaceRowGap -> R.string.app_tokens_dimension_space_rowGapHeader_text + TokenProperty.SpaceRowGapWithIcon -> R.string.app_tokens_dimension_space_rowGapWithIconHeader_text + TokenProperty.SpaceScaled -> R.string.app_tokens_dimension_space_scaledHeader_text + else -> null + } + if (textResId != null) { + Text( + modifier = modifier.background(color = OudsColorKeyToken.Background.Emphasized.value), + text = stringResource(id = textResId), + color = OudsColorKeyToken.Content.DefaultOnBgEmphasized.value, + style = OudsTypographyKeyToken.BodyDefaultMedium.value + ) + } +} + +@Composable +private fun SpaceHeaderImage( + spaceTokenProperty: TokenProperty, + modifier: Modifier = Modifier, + alignment: Alignment = Alignment.Center +) { + val imageResId = when (spaceTokenProperty) { + TokenProperty.SpacePaddingInlineWithIcon, + TokenProperty.SpacePaddingStackWithIcon, + TokenProperty.SpaceColumnGapWithIcon, + TokenProperty.SpaceRowGapWithIcon -> R.drawable.ic_design_token_figma_no_padding + TokenProperty.SpacePaddingInlineWithArrow, + TokenProperty.SpaceColumnGapWithArrow -> R.drawable.ic_chevron_down + else -> null + } + + if (imageResId != null) { + val paddingValue = 1.dp + val paddingValues = when (spaceTokenProperty) { + TokenProperty.SpacePaddingInlineWithIcon -> PaddingValues(start = paddingValue) + TokenProperty.SpacePaddingStackWithIcon -> PaddingValues(top = paddingValue) + TokenProperty.SpaceColumnGapWithIcon -> PaddingValues(end = paddingValue) + TokenProperty.SpaceRowGapWithIcon -> PaddingValues(bottom = paddingValue) + else -> PaddingValues(all = 0.dp) + } + + Image( + modifier = modifier + .background(color = OudsColorKeyToken.Background.Emphasized.value) + .padding(paddingValues = paddingValues), + painter = painterResource(id = imageResId), + contentDescription = null, + alignment = alignment + ) + } +} + +@UiModePreviews.Default +@Composable +private fun PreviewGridHeader() = OudsPreview { + GridHeader() +} + +@UiModePreviews.Default +@Composable +private fun PreviewSpaceHeader(@PreviewParameter(SpaceHeaderPreviewParameterProvider::class) parameter: TokenProperty) = + OudsPreview { + SpaceHeader(parameter) + } + +private class SpaceHeaderPreviewParameterProvider : + BasicPreviewParameterProvider>(*previewParameterValues.toTypedArray()) + +private val previewParameterValues: List> + get() = listOf( + TokenProperty.SpaceScaled, +// TokenProperty.SpaceFixed, +// TokenProperty.SpacePaddingInline, +// TokenProperty.SpacePaddingInlineWithIcon, +// TokenProperty.SpacePaddingInlineWithArrow, +// TokenProperty.SpacePaddingStack, +// TokenProperty.SpacePaddingStackWithIcon, +// TokenProperty.SpacePaddingInset, +// TokenProperty.SpaceColumnGap, +// TokenProperty.SpaceColumnGapWithIcon, +// TokenProperty.SpaceColumnGapWithArrow, +// TokenProperty.SpaceRowGap, +// TokenProperty.SpaceRowGapWithIcon + ) diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt index 03c2bb08..0b6a3cf7 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt @@ -271,26 +271,3 @@ fun SpaceIllustrationBox( enum class SpaceOrientation { Horizontal, Vertical } - -@Composable -fun GridIllustrations() { - Column( - modifier = Modifier.padding(horizontal = OudsSpaceKeyToken.Fixed.Medium.value), - verticalArrangement = Arrangement.spacedBy(OudsSpaceKeyToken.Fixed.Medium.value) - ) { - val resourceIds = listOf( - R.drawable.il_tokens_grid_column_margin, - R.drawable.il_tokens_grid_min_width, - R.drawable.il_tokens_grid_max_width - ) - resourceIds.forEach { - Image( - modifier = Modifier - .fillMaxWidth() - .background(OudsColorKeyToken.Background.Emphasized.value), - painter = painterResource(id = it), - contentDescription = null - ) - } - } -} diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokensScreen.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokensScreen.kt index e6375c74..7e2d27a2 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokensScreen.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokensScreen.kt @@ -37,7 +37,7 @@ fun TokensScreen(onTokenCategoryClick: (Long) -> Unit) { } @Composable -private fun TokensScreen(tokenCategories: List, onTokenCategoryClick: (Long) -> Unit) { +private fun TokensScreen(tokenCategories: List>, onTokenCategoryClick: (Long) -> Unit) { Screen { Column( modifier = Modifier diff --git a/app/src/main/java/com/orange/ouds/app/ui/utilities/composable/DetailScreenHeader.kt b/app/src/main/java/com/orange/ouds/app/ui/utilities/composable/DetailScreenHeader.kt index 62a6fe74..4ba19fd7 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/utilities/composable/DetailScreenHeader.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/utilities/composable/DetailScreenHeader.kt @@ -54,7 +54,9 @@ fun DetailScreenHeader( ) DetailScreenDescription( - modifier = Modifier.padding(all = OudsSpaceKeyToken.Fixed.Medium.value), + modifier = Modifier + .padding(horizontal = OudsSpaceKeyToken.Fixed.Medium.value) + .padding(top = OudsSpaceKeyToken.Fixed.Medium.value), descriptionRes = descriptionRes ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 53fc88fc..d57de469 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,18 +62,31 @@ Space Space refers to the measurements used to define the spacing between UI elements. Scaled + Scaled spacing refers to spacing that adjusts dynamically based on factors like container size, screen resolution, or layout elements. Fixed + Fixed spacing refers to a constant distance between elements that remains the same regardless of factors like container size, screen resolution, or layout changes. Padding inline + Padding inline includes the left and right padding of an object or a group of objects. Padding inline with icon + Padding inline with icon includes the padding of a group of objects that includes an icon. Padding inline with arrow + Padding inline with arrow includes the padding of a group of objects that includes an arrow. Padding stack + Padding stack includes the top and bottom padding. Padding stack with icon + Padding stack with icon includes the padding of a group of objects that includes an icon. Padding inset + Padding inset includes the left, right, top, and bottom padding, with all parameters being equal. Column gap + Gap inline includes the vertical spacing between objects. Column gap with icon + Gap inline with icon includes the vertical spacing between objects, one of which is an icon. Column gap with arrow + Gap inline with arrow includes the vertical spacing between objects, one of which is an arrow. Row gap + Gap stack includes the horizontal spacing between objects. Row gap with icon + Gap stack with icon includes the horizontal spacing between objects, one of which is an icon. Size