diff --git a/mobile/kmp/sample/src/commonMain/kotlin/com/atls/hyperion/sample/App.kt b/mobile/kmp/sample/src/commonMain/kotlin/com/atls/hyperion/sample/App.kt index cfcc0b92e..e2eabc539 100644 --- a/mobile/kmp/sample/src/commonMain/kotlin/com/atls/hyperion/sample/App.kt +++ b/mobile/kmp/sample/src/commonMain/kotlin/com/atls/hyperion/sample/App.kt @@ -4,16 +4,25 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import com.atls.hyperion.storybook.fragments.storybook.Storybook import com.atls.hyperion.ui.components.avatar.stories.AvatarStory +import com.atls.hyperion.ui.components.bottomBar.stories.BottomBarStory import com.atls.hyperion.ui.components.button.stories.ButtonStory import com.atls.hyperion.ui.components.card.stories.CardStory +import com.atls.hyperion.ui.components.carousel.stories.CarouselStory import com.atls.hyperion.ui.components.checkbox.stories.CheckboxStory import com.atls.hyperion.ui.components.divider.stories.DividerStory import com.atls.hyperion.ui.components.input.stories.InputStory +import com.atls.hyperion.ui.components.list.stories.ListStories import com.atls.hyperion.ui.components.modal.bottom.stories.BottomDialogStory import com.atls.hyperion.ui.components.modal.popup.stories.PopupStory +import com.atls.hyperion.ui.components.pagination.stories.PaginationStory +import com.atls.hyperion.ui.components.placeholder.stories.PlaceholderStory +import com.atls.hyperion.ui.components.progress.stories.ProgressStory import com.atls.hyperion.ui.components.switch.stories.SwitchStory -import com.atls.hyperion.ui.fragment.datepicker.stories.DatePickerStory -import com.atls.hyperion.ui.fragment.datepicker.stories.DateRangePickerStory +import com.atls.hyperion.ui.components.toast.stories.ToastStories +import com.atls.hyperion.ui.components.tooltip.stories.TextTooltipStories +import com.atls.hyperion.ui.components.topBar.stories.TopBarStory +import com.atls.hyperion.ui.fragments.datepicker.stories.DatePickerStory +import com.atls.hyperion.ui.fragments.datepicker.stories.DateRangePickerStory import com.atls.hyperion.ui.primitives.stories.LinkStory import com.atls.hyperion.ui.primitives.stories.TextStory @@ -24,17 +33,26 @@ fun App() { components = listOf( AvatarStory(), BottomDialogStory(), + BottomBarStory(), ButtonStory(), + CardStory(), + CarouselStory(), CheckboxStory(), DatePickerStory(), DateRangePickerStory(), DividerStory(), InputStory(), + PaginationStory(), + PlaceholderStory(), PopupStory(), + ProgressStory(), SwitchStory(), - CardStory(), TextStory(), - LinkStory() + TopBarStory(), + LinkStory(), + ListStories(), + ToastStories(), + TextTooltipStories() ) ) } diff --git a/mobile/kmp/settings.gradle.kts b/mobile/kmp/settings.gradle.kts index 583813c1d..c9bdb332b 100644 --- a/mobile/kmp/settings.gradle.kts +++ b/mobile/kmp/settings.gradle.kts @@ -17,4 +17,3 @@ rootProject.name = "hyperion" include(":sample") include(":ui") include(":storybook") -include(":storybook-api") diff --git a/mobile/kmp/storybook/src/commonMain/kotlin/com/atls/hyperion/storybook/shared/ui/ComponentVariants.kt b/mobile/kmp/storybook/src/commonMain/kotlin/com/atls/hyperion/storybook/shared/ui/ComponentVariants.kt index dab73d455..f1ab16545 100644 --- a/mobile/kmp/storybook/src/commonMain/kotlin/com/atls/hyperion/storybook/shared/ui/ComponentVariants.kt +++ b/mobile/kmp/storybook/src/commonMain/kotlin/com/atls/hyperion/storybook/shared/ui/ComponentVariants.kt @@ -7,8 +7,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material.Divider import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -27,7 +25,6 @@ fun ComponentVariants( Column( modifier = Modifier .fillMaxWidth() - .verticalScroll(rememberScrollState()) .padding(Padding.medium), verticalArrangement = Arrangement.spacedBy(Padding.large) ) { diff --git a/mobile/kmp/ui/src/commonMain/composeResources/drawable/placeholder.xml b/mobile/kmp/ui/src/commonMain/composeResources/drawable/placeholder.xml new file mode 100644 index 000000000..da6a2b6f1 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/composeResources/drawable/placeholder.xml @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Component.kt new file mode 100644 index 000000000..39cd35911 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Component.kt @@ -0,0 +1,73 @@ +package com.atls.hyperion.ui.components.bottomBar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.bottomBar.model.BottomBarItem +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.BottomBarAppearance +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.primary +import com.atls.hyperion.ui.components.bottomBar.styles.shape.BottomBarShape + +@Composable +fun BottomBar( + modifier: Modifier = Modifier, + appearance: BottomBarAppearance = BottomBarAppearance.primary(), + shape: BottomBarShape, + tabArrangement: Arrangement.Horizontal, + content: @Composable RowScope.() -> Unit +) { + Surface( + modifier = modifier.fillMaxWidth(), + elevation = shape.elevation, + shape = shape.shape + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(appearance.colors.backgroundColor) + .height(shape.height) + .padding(horizontal = shape.tabSpacing), + horizontalArrangement = tabArrangement, + verticalAlignment = Alignment.CenterVertically + ) { + content() + } + } +} + +@Composable +fun BottomBar( + items: List, + selectedItemIndex: Int, + onItemClick: (Int) -> Unit, + modifier: Modifier = Modifier, + appearance: BottomBarAppearance = BottomBarAppearance.primary(), + shape: BottomBarShape, + tabArrangement: Arrangement.Horizontal +) { + BottomBar( + modifier = modifier, + appearance = appearance, + shape = shape, + tabArrangement = tabArrangement + ) { + items.forEachIndexed { index, item -> + BottomBarTab( + icon = item.icon, + label = item.label, + selected = index == selectedItemIndex, + onClick = { onItemClick(index) }, + appearance = appearance, + shape = shape + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Tab.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Tab.kt new file mode 100644 index 000000000..f74635171 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/Tab.kt @@ -0,0 +1,74 @@ +package com.atls.hyperion.ui.components.bottomBar + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.material.Icon +import androidx.compose.material.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.graphics.painter.Painter +import androidx.compose.ui.text.style.TextAlign +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.BottomBarAppearance +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.Colors +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.primary +import com.atls.hyperion.ui.components.bottomBar.styles.shape.BottomBarShape + +@Composable +fun BottomBarTab( + icon: Painter, + label: String?, + selected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, + appearance: BottomBarAppearance = BottomBarAppearance.primary(), + shape: BottomBarShape, +) { + val tabColors = appearance.colors.tabColors + val iconColor = if (selected) tabColors.activeColor else tabColors.inactiveColor + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = onClick + ) + ) { + Icon( + painter = icon, + contentDescription = label ?: "", + tint = iconColor, + modifier = Modifier.size( + when (shape) { + is BottomBarShape.WithLabel -> shape.iconSize + is BottomBarShape.WithoutLabel -> shape.iconSize + } + ) + ) + + if (shape is BottomBarShape.WithLabel && label != null) { + Spacer(modifier = Modifier.height(shape.labelPadding)) + + val labelColor = when (val colors = tabColors) { + is Colors.TabColors.WithLabel -> + if (selected) colors.activeLabelColor else colors.inactiveLabelColor + + is Colors.TabColors.WithoutLabel -> + iconColor + } + + Text( + text = label, + color = labelColor, + style = shape.labelTypography, + textAlign = TextAlign.Center + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/model/Item.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/model/Item.kt new file mode 100644 index 000000000..cbc56b653 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/model/Item.kt @@ -0,0 +1,8 @@ +package com.atls.hyperion.ui.components.bottomBar.model + +import androidx.compose.ui.graphics.painter.Painter + +data class BottomBarItem( + val icon: Painter, + val label: String? = null +) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Component.kt new file mode 100644 index 000000000..d541ddc64 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Component.kt @@ -0,0 +1,77 @@ +package com.atls.hyperion.ui.components.bottomBar.stories + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.components.bottomBar.model.BottomBarItem +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class BottomBarStory : ComponentExample { + override val name: String = "BottomBar" + + @Composable + override fun Content() { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(bottom = Space.xl3) + ) { + + val itemsWithLabels = listOf( + BottomBarItem(homePainter, "Home"), + BottomBarItem(favoritePainter, "Favorites"), + BottomBarItem(profilePainter, "Profile"), + BottomBarItem(settingsPainter, "Settings") + ) + + val itemsWithoutLabels = itemsWithLabels.map { it.copy(label = null) } + + var tabPosition by remember { mutableStateOf(Arrangement.Center) } + + Column(modifier = Modifier.fillMaxWidth().padding(Space.md)) { + Text("Tab Position:") + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(vertical = Space.sm) + ) { + RadioButton( + selected = tabPosition == Arrangement.SpaceAround, + onClick = { tabPosition = Arrangement.SpaceAround }) + Text("Space around", modifier = Modifier.padding(start = Space.xs, end = Space.sm)) + + RadioButton( + selected = tabPosition == Arrangement.Center, + onClick = { tabPosition = Arrangement.Center }) + Text("Center", modifier = Modifier.padding(start = Space.xs, end = Space.sm)) + + RadioButton( + selected = tabPosition == Arrangement.SpaceBetween, + onClick = { tabPosition = Arrangement.SpaceBetween }) + Text("Space between", modifier = Modifier.padding(start = Space.xs)) + } + } + + BottomBarWithLabelsVariants(itemsWithLabels, tabPosition) + + Spacer(Modifier.height(Space.xl2)) + + BottomBarWithoutLabelsVariants(itemsWithoutLabels, tabPosition) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Painters.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Painters.kt new file mode 100644 index 000000000..ab6e31085 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/Painters.kt @@ -0,0 +1,91 @@ +package com.atls.hyperion.ui.components.bottomBar.stories + +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.graphics.painter.Painter +import kotlin.math.PI + +val homePainter: Painter = object : Painter() { + override val intrinsicSize = Size(24f, 24f) + override fun DrawScope.onDraw() { + drawRect( + color = Color.Black, + topLeft = Offset(size.width * 0.2f, size.height * 0.3f), + size = Size(size.width * 0.6f, size.height * 0.6f) + ) + drawLine( + color = Color.Black, + start = Offset(size.width * 0.2f, size.height * 0.3f), + end = Offset(size.width * 0.5f, size.height * 0.1f) + ) + drawLine( + color = Color.Black, + start = Offset(size.width * 0.5f, size.height * 0.1f), + end = Offset(size.width * 0.8f, size.height * 0.3f) + ) + } +} + +val favoritePainter: Painter = object : Painter() { + override val intrinsicSize = Size(24f, 24f) + override fun DrawScope.onDraw() { + val cx = size.width / 2 + val cy = size.height / 2 + val r = size.width / 3 + drawCircle( + color = Color.Black, + center = Offset(cx, cy), + radius = r, + style = Stroke(2f) + ) + drawCircle(color = Color.Black, center = Offset(cx, cy), radius = r / 2) + } +} + +val profilePainter: Painter = object : Painter() { + override val intrinsicSize = Size(24f, 24f) + override fun DrawScope.onDraw() { + drawCircle( + color = Color.Black, + center = Offset(size.width / 2, size.height * 0.35f), + radius = size.width * 0.2f + ) + drawRect( + color = Color.Black, + topLeft = Offset(size.width * 0.3f, size.height * 0.5f), + size = Size(size.width * 0.4f, size.height * 0.4f) + ) + } +} + +val settingsPainter: Painter = object : Painter() { + override val intrinsicSize = Size(24f, 24f) + override fun DrawScope.onDraw() { + drawCircle( + color = Color.Black, + center = Offset(size.width / 2, size.height / 2), + radius = size.width * 0.3f, + style = Stroke(2f) + ) + for (i in 0 until 8) { + val angle = PI * i / 4 + val sx = + size.width / 2 + (size.width * 0.35f * kotlin.math.cos(angle)).toFloat() + val sy = + size.height / 2 + (size.height * 0.35f * kotlin.math.sin(angle)).toFloat() + val ex = + size.width / 2 + (size.width * 0.45f * kotlin.math.cos(angle)).toFloat() + val ey = + size.height / 2 + (size.height * 0.45f * kotlin.math.sin(angle)).toFloat() + drawLine( + color = Color.Black, + start = Offset(sx, sy), + end = Offset(ex, ey), + strokeWidth = 2f + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithLabels.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithLabels.kt new file mode 100644 index 000000000..9461072f0 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithLabels.kt @@ -0,0 +1,43 @@ +package com.atls.hyperion.ui.components.bottomBar.stories + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.bottomBar.BottomBar +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.BottomBarAppearance +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.dark +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.primary +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.secondary +import com.atls.hyperion.ui.components.bottomBar.styles.shape.BottomBarShape.WithLabel +import com.atls.hyperion.ui.components.bottomBar.styles.shape.default +import com.atls.hyperion.ui.components.bottomBar.styles.shape.elevated +import com.atls.hyperion.ui.components.bottomBar.styles.shape.rounded + +@Composable +fun BottomBarWithLabelsVariants(items: List, tabPosition: Arrangement.Horizontal) { + ComponentVariants( + name = "BottomBar (With Labels)", + appearances = listOf( + "Primary" to { BottomBarAppearance.primary() }, + "Secondary" to { BottomBarAppearance.secondary() }, + "Dark" to { BottomBarAppearance.dark() } + ), + shapes = listOf( + "Default" to { WithLabel.default() }, + "Elevated" to { WithLabel.elevated() }, + "Rounded" to { WithLabel.rounded() } + ) + ) { appearance, shape -> + val selectedIndex = remember { mutableStateOf(0) } + BottomBar( + items, + selectedIndex.value, + { selectedIndex.value = it }, + appearance = appearance, + shape = shape, + tabArrangement = tabPosition + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithoutLabels.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithoutLabels.kt new file mode 100644 index 000000000..c7148c4aa --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/stories/WithoutLabels.kt @@ -0,0 +1,43 @@ +package com.atls.hyperion.ui.components.bottomBar.stories + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.bottomBar.BottomBar +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.BottomBarAppearance +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.darkWithoutLabel +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.primaryWithoutLabel +import com.atls.hyperion.ui.components.bottomBar.styles.appearance.secondaryWithoutLabel +import com.atls.hyperion.ui.components.bottomBar.styles.shape.BottomBarShape.WithoutLabel +import com.atls.hyperion.ui.components.bottomBar.styles.shape.default +import com.atls.hyperion.ui.components.bottomBar.styles.shape.elevated +import com.atls.hyperion.ui.components.bottomBar.styles.shape.rounded + +@Composable +fun BottomBarWithoutLabelsVariants(items: List, tabPosition: Arrangement.Horizontal) { + ComponentVariants( + name = "BottomBar (Without Labels)", + appearances = listOf( + "Primary" to { BottomBarAppearance.primaryWithoutLabel() }, + "Secondary" to { BottomBarAppearance.secondaryWithoutLabel() }, + "Dark" to { BottomBarAppearance.darkWithoutLabel() } + ), + shapes = listOf( + "Default" to { WithoutLabel.default() }, + "Rounded" to { WithoutLabel.rounded() }, + "Elevated" to { WithoutLabel.elevated() } + ) + ) { appearance, shape -> + val selectedIndex = remember { mutableStateOf(0) } + BottomBar( + items, + selectedIndex.value, + { selectedIndex.value = it }, + appearance = appearance, + shape = shape, + tabArrangement = tabPosition + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/Size.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/Size.kt new file mode 100644 index 000000000..b93ecd0cd --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/Size.kt @@ -0,0 +1,7 @@ +package com.atls.hyperion.ui.components.bottomBar.styles + +import androidx.compose.ui.unit.dp + +object BottomBarSize { + val defaultHeight = 56.dp +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Appearance.kt new file mode 100644 index 000000000..380a2cae5 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Appearance.kt @@ -0,0 +1,7 @@ +package com.atls.hyperion.ui.components.bottomBar.styles.appearance + +data class BottomBarAppearance( + val colors: Colors +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Colors.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Colors.kt new file mode 100644 index 000000000..0cb58c4f3 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Colors.kt @@ -0,0 +1,36 @@ +package com.atls.hyperion.ui.components.bottomBar.styles.appearance + +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.ui.theme.tokens.effects.Alpha + +sealed class Colors { + abstract val backgroundColor: Color + abstract val dividerColor: Color + abstract val tabColors: TabColors + + sealed class TabColors { + abstract val activeColor: Color + abstract val inactiveColor: Color + abstract val rippleColor: Color + + data class WithLabel( + override val activeColor: Color, + override val inactiveColor: Color, + val activeLabelColor: Color, + val inactiveLabelColor: Color, + override val rippleColor: Color = activeColor.copy(alpha = Alpha.micro) + ) : TabColors() + + data class WithoutLabel( + override val activeColor: Color, + override val inactiveColor: Color, + override val rippleColor: Color = activeColor.copy(alpha = Alpha.micro) + ) : TabColors() + } + + data class Default( + override val backgroundColor: Color, + override val dividerColor: Color, + override val tabColors: TabColors + ) : Colors() +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Variants.kt new file mode 100644 index 000000000..87a2e15ff --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/appearance/Variants.kt @@ -0,0 +1,89 @@ +package com.atls.hyperion.ui.components.bottomBar.styles.appearance + +import com.atls.hyperion.ui.theme.tokens.effects.Alpha +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +fun BottomBarAppearance.Companion.primary(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.white, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithLabel( + activeColor = ThemeColors.Palette.blueProtective, + inactiveColor = ThemeColors.Palette.gray, + activeLabelColor = ThemeColors.Palette.blueProtective, + inactiveLabelColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.blueProtective.copy(alpha = Alpha.micro) + ) + ) + ) + +fun BottomBarAppearance.Companion.secondary(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.white, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithLabel( + activeColor = ThemeColors.Palette.green, + inactiveColor = ThemeColors.Palette.gray, + activeLabelColor = ThemeColors.Palette.green, + inactiveLabelColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.green.copy(alpha = Alpha.micro) + ) + ) + ) + +fun BottomBarAppearance.Companion.dark(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.black, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithLabel( + activeColor = ThemeColors.Palette.white, + inactiveColor = ThemeColors.Palette.gray, + activeLabelColor = ThemeColors.Palette.white, + inactiveLabelColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.white.copy(alpha = Alpha.micro) + ) + ) + ) + + +fun BottomBarAppearance.Companion.primaryWithoutLabel(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.white, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithoutLabel( + activeColor = ThemeColors.Palette.blueProtective, + inactiveColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.blueProtective.copy(alpha = Alpha.micro) + ) + ) + ) + +fun BottomBarAppearance.Companion.secondaryWithoutLabel(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.white, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithoutLabel( + activeColor = ThemeColors.Palette.green, + inactiveColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.green.copy(alpha = Alpha.micro) + ) + ) + ) + +fun BottomBarAppearance.Companion.darkWithoutLabel(): BottomBarAppearance = + BottomBarAppearance( + colors = Colors.Default( + backgroundColor = ThemeColors.Palette.black, + dividerColor = ThemeColors.Palette.gray, + tabColors = Colors.TabColors.WithoutLabel( + activeColor = ThemeColors.Palette.white, + inactiveColor = ThemeColors.Palette.gray, + rippleColor = ThemeColors.Palette.white.copy(alpha = Alpha.micro) + ) + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Shape.kt new file mode 100644 index 000000000..bb9cde80f --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Shape.kt @@ -0,0 +1,42 @@ +package com.atls.hyperion.ui.components.bottomBar.styles.shape + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.Dp + +sealed class BottomBarShape { + + abstract val height: Dp + abstract val elevation: Dp + abstract val cornerRadius: Dp + abstract val dividerWidth: Dp + abstract val tabSpacing: Dp + abstract val iconSize: Dp + abstract val shape: RoundedCornerShape + + data class WithLabel( + override val height: Dp, + override val elevation: Dp, + override val cornerRadius: Dp, + override val dividerWidth: Dp, + override val tabSpacing: Dp, + override val iconSize: Dp, + val labelPadding: Dp, + val labelTypography: TextStyle, + override val shape: RoundedCornerShape = RoundedCornerShape(cornerRadius) + ) : BottomBarShape() { + companion object + } + + data class WithoutLabel( + override val height: Dp, + override val elevation: Dp, + override val cornerRadius: Dp, + override val dividerWidth: Dp, + override val tabSpacing: Dp, + override val iconSize: Dp, + override val shape: RoundedCornerShape = RoundedCornerShape(cornerRadius) + ) : BottomBarShape() { + companion object + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Variants.kt new file mode 100644 index 000000000..78ef9d600 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/bottomBar/styles/shape/Variants.kt @@ -0,0 +1,95 @@ +package com.atls.hyperion.ui.components.bottomBar.styles.shape + +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.dp +import com.atls.hyperion.ui.components.bottomBar.styles.BottomBarSize +import com.atls.hyperion.ui.primitives.icon.IconSize +import com.atls.hyperion.ui.theme.tokens.layout.BorderStroke +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius +import com.atls.hyperion.ui.theme.tokens.layout.Elevation +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.FontWeight +import com.atls.hyperion.ui.theme.typography.NunitoSansFontFamily + +@Composable +fun BottomBarShape.WithLabel.Companion.default() = + BottomBarShape.WithLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.zero, + cornerRadius = CornerRadius.zero, + dividerWidth = BorderStroke.tiny, + tabSpacing = Space.xs2, + iconSize = IconSize.medium, + labelPadding = Space.xs4, + labelTypography = TextStyle( + fontSize = FontSize.xs3, + fontWeight = FontWeight.medium, + fontFamily = NunitoSansFontFamily() + ) + ) + +@Composable +fun BottomBarShape.WithLabel.Companion.elevated() = + BottomBarShape.WithLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.medium, + cornerRadius = CornerRadius.zero, + dividerWidth = BorderStroke.none, + tabSpacing = Space.xs2, + iconSize = IconSize.medium, + labelPadding = Space.xs4, + labelTypography = TextStyle( + fontSize = FontSize.xs3, + fontWeight = FontWeight.medium, + fontFamily = NunitoSansFontFamily() + ) + ) + +@Composable +fun BottomBarShape.WithLabel.Companion.rounded() = + BottomBarShape.WithLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.tiny, + cornerRadius = CornerRadius.xl2_5, + dividerWidth = BorderStroke.none, + tabSpacing = Space.xs2, + iconSize = IconSize.medium, + labelPadding = Space.xs4, + labelTypography = TextStyle( + fontSize = FontSize.xs3, + fontWeight = FontWeight.medium, + fontFamily = NunitoSansFontFamily() + ) + ) + +fun BottomBarShape.WithoutLabel.Companion.default() = + BottomBarShape.WithoutLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.zero, + cornerRadius = CornerRadius.zero, + dividerWidth = 1.dp, + tabSpacing = Space.xs2, + iconSize = IconSize.medium + ) + +fun BottomBarShape.WithoutLabel.Companion.elevated() = + BottomBarShape.WithoutLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.medium, + cornerRadius = CornerRadius.zero, + dividerWidth = BorderStroke.none, + tabSpacing = Space.xs2, + iconSize = IconSize.medium + ) + +fun BottomBarShape.WithoutLabel.Companion.rounded() = + BottomBarShape.WithoutLabel( + height = BottomBarSize.defaultHeight, + elevation = Elevation.tiny, + cornerRadius = CornerRadius.xl2_5, + dividerWidth = BorderStroke.none, + tabSpacing = Space.xs2, + iconSize = IconSize.medium + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/Button.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/Component.kt similarity index 100% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/Button.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/Component.kt diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/stories/Component.kt index af661f4a5..e3a0d064f 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/stories/Component.kt @@ -42,13 +42,13 @@ class ButtonStory : ComponentExample { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = Space.g12) + .padding(horizontal = Space.sm) ) { Text(modifier = Modifier.weight(Weight.full), text = "Enabled") - HorizontalSpacer(Space.g12) + HorizontalSpacer(Space.sm) Switch(checked = enabled, onCheckedChange = { enabled = it }) } - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) ComponentVariants( name = "Button", diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/styles/shape/Variants.kt index ffb849f56..39a9f62b9 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/styles/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/button/styles/shape/Variants.kt @@ -13,7 +13,7 @@ import com.atls.hyperion.ui.theme.typography.LineHeights fun ButtonShape.Companion.huge(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g24, vertical = Space.g16), + paddings = PaddingValues(horizontal = Space.xl3, vertical = Space.lg), typography = TextStyle(fontSize = FontSize.xl3, lineHeight = LineHeights.xl4), borderStroke = BorderStroke.none ) @@ -22,7 +22,7 @@ fun ButtonShape.Companion.huge(): ButtonShape = fun ButtonShape.Companion.large(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g24, vertical = Space.g14), + paddings = PaddingValues(horizontal = Space.xl3, vertical = Space.md), typography = TextStyle(fontSize = FontSize.xl2, lineHeight = LineHeights.xl3), borderStroke = BorderStroke.none ) @@ -31,7 +31,7 @@ fun ButtonShape.Companion.large(): ButtonShape = fun ButtonShape.Companion.semiMedium(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g20, vertical = Space.g12), + paddings = PaddingValues(horizontal = Space.xl, vertical = Space.sm), typography = TextStyle(fontSize = FontSize.lg, lineHeight = LineHeights.xl), borderStroke = BorderStroke.none ) @@ -40,7 +40,7 @@ fun ButtonShape.Companion.semiMedium(): ButtonShape = fun ButtonShape.Companion.medium(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g16, vertical = Space.g10), + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.xs), typography = TextStyle(fontSize = FontSize.md, lineHeight = LineHeights.md), borderStroke = BorderStroke.none ) @@ -49,7 +49,7 @@ fun ButtonShape.Companion.medium(): ButtonShape = fun ButtonShape.Companion.normal(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g24, vertical = Space.g8), + paddings = PaddingValues(horizontal = Space.xl3, vertical = Space.xs2), typography = TextStyle(fontSize = FontSize.xs, lineHeight = LineHeights.sm), borderStroke = BorderStroke.none ) @@ -58,7 +58,7 @@ fun ButtonShape.Companion.normal(): ButtonShape = fun ButtonShape.Companion.small(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl4, - paddings = PaddingValues(horizontal = Space.g16, vertical = Space.g6), + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.xs3), typography = TextStyle(fontSize = FontSize.xs, lineHeight = LineHeights.xs), borderStroke = BorderStroke.none ) @@ -67,7 +67,7 @@ fun ButtonShape.Companion.small(): ButtonShape = fun ButtonShape.Companion.smallSizeMediumRadii(): ButtonShape = ButtonShape( cornerRadius = CornerRadius.xl2_5, - paddings = PaddingValues(horizontal = Space.g16, vertical = Space.g6), + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.xs3), typography = TextStyle(fontSize = FontSize.xs, lineHeight = LineHeights.xs), borderStroke = BorderStroke.none ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/card/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/card/style/shape/Variants.kt index 7fa6617d5..53a0e9c84 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/card/style/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/card/style/shape/Variants.kt @@ -10,6 +10,6 @@ import com.atls.hyperion.ui.theme.tokens.layout.Space fun CardShape.Companion.medium(): CardShape = CardShape( cornerRadius = CornerRadius.xl, - padding = PaddingValues(Space.g16), + padding = PaddingValues(Space.lg), borderWidth = BorderStroke.none ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/Component.kt new file mode 100644 index 000000000..1463f1643 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/Component.kt @@ -0,0 +1,38 @@ +package com.atls.hyperion.ui.components.carousel + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.carousel.style.shape.CarouselShape +import com.atls.hyperion.ui.components.carousel.style.shape.default + +@Composable +fun Carousel( + modifier: Modifier = Modifier, + pageCount: Int, + shape: CarouselShape = CarouselShape.default(), + pagerState: PagerState = rememberPagerState(pageCount = { + pageCount + }), + content: @Composable (page: Int) -> Unit +) { + + HorizontalPager( + state = pagerState, + contentPadding = PaddingValues(horizontal = shape.peekWidth + shape.padding), + modifier = modifier.fillMaxWidth(), + pageSpacing = shape.padding + ) { page -> + Box( + modifier = Modifier + .fillMaxWidth() + ) { + content(page) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/InfiniteOverlay.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/InfiniteOverlay.kt new file mode 100644 index 000000000..c4eedda3d --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/InfiniteOverlay.kt @@ -0,0 +1,166 @@ +package com.atls.hyperion.ui.components.carousel + +import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.zIndex +import com.atls.hyperion.ui.components.carousel.lib.calculateDistance +import com.atls.hyperion.ui.components.carousel.lib.centerOfItem +import com.atls.hyperion.ui.components.carousel.lib.centerOfViewport +import com.atls.hyperion.ui.components.carousel.lib.normalizedStartIndex +import com.atls.hyperion.ui.theme.tokens.effects.Alpha +import com.atls.hyperion.ui.theme.tokens.layout.Space +import kotlin.math.abs + +@Composable +fun InfiniteOverlayCarousel( + items: List, + modifier: Modifier = Modifier, + baseCardSize: Dp, + sizeStep: Dp, + visibleItemCount: Int, + alphaStep: Float, + minAlpha: Float, + centerIndexState: MutableState, + itemContent: @Composable (item: T, size: Dp, alpha: Float, zIndex: Float) -> Unit +) { + require(items.isNotEmpty()) { "Items list must not be empty" } + require(visibleItemCount > 0) { "Visible item count must be positive" } + require(visibleItemCount % 2 == 1) { "Visible item count should be odd for symmetrical layout" } + + val startIndex = remember(items) { + normalizedStartIndex(centerIndexState.value, items.size) + } + + val listState = rememberLazyListState(initialFirstVisibleItemIndex = startIndex) + val density = LocalDensity.current + val halfCount = (visibleItemCount - 1) / 2 + + BoxWithConstraints(modifier = modifier + .height(baseCardSize)) { + val screenWidth = maxWidth + val screenWidthPx = with(density) { screenWidth.toPx() } + val baseCardSizePx = with(density) { baseCardSize.toPx() } + + val spacingPx = if (visibleItemCount == 1) { + 0f + } else { + (screenWidthPx - visibleItemCount * baseCardSizePx) / (visibleItemCount) + } + + val spacing = with(density) { spacingPx.toDp() } + val itemStepPx = baseCardSizePx + spacingPx + + val flingBehavior = rememberSnapFlingBehavior(lazyListState = listState) + + val viewportCenter by remember { + derivedStateOf { + centerOfViewport( + listState.layoutInfo.viewportStartOffset, + listState.layoutInfo.viewportSize.width + ) + } + } + + val currentCenterIndex by remember { + derivedStateOf { + val visibleItems = listState.layoutInfo.visibleItemsInfo + visibleItems.minByOrNull { info -> + abs(centerOfItem(info.offset, info.size) - viewportCenter) + }?.index ?: listState.firstVisibleItemIndex + } + } + + LaunchedEffect(currentCenterIndex) { + centerIndexState.value = currentCenterIndex + } + + LaunchedEffect(listState) { + snapshotFlow { listState.layoutInfo.visibleItemsInfo.isNotEmpty() } + .collect { ready -> + if (ready && !listState.isScrollInProgress) { + val visibleItems = listState.layoutInfo.visibleItemsInfo + val centerItemInfo = visibleItems.minByOrNull { info -> + abs(centerOfItem(info.offset, info.size) - viewportCenter) + } + centerItemInfo?.let { info -> + val realIndex = info.index % items.size + val middle = Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2) % items.size + val targetIndex = middle + realIndex + val offset = (info.size / 2) - (listState.layoutInfo.viewportSize.width / 2) + listState.scrollToItem(targetIndex, offset) + } + } + } + } + + val startDrawIndex by remember { + derivedStateOf { currentCenterIndex - halfCount } + } + val endDrawIndex by remember { + derivedStateOf { currentCenterIndex + halfCount } + } + + LazyRow( + state = listState, + flingBehavior = flingBehavior, + contentPadding = PaddingValues(Space.zero), + horizontalArrangement = Arrangement.spacedBy(spacing), + verticalAlignment = Alignment.CenterVertically, + ) { + items( + count = Int.MAX_VALUE, + key = { it } + ) { index -> + if (index !in startDrawIndex..endDrawIndex) { + Spacer(Modifier.width(baseCardSize)) + return@items + } + + val currentItemInfo = + listState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index } + val distance = currentItemInfo?.let { info -> + calculateDistance( + centerOfItem(info.offset, info.size), + viewportCenter, + itemStepPx + ) + } ?: abs(index - currentCenterIndex).toFloat() + + val clampedDistance = distance.coerceAtMost(halfCount.toFloat()) + val size = baseCardSize - (sizeStep * clampedDistance) + val alpha = (Alpha.full - (alphaStep * clampedDistance)).coerceAtLeast(minAlpha) + val zIndex = (visibleItemCount - clampedDistance) + + val item = items[index % items.size] + + Box( + modifier = Modifier + .width(baseCardSize) + .zIndex(zIndex), + contentAlignment = Alignment.Center + ) { + itemContent(item, size, alpha, zIndex) + } + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/WithPagination.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/WithPagination.kt new file mode 100644 index 000000000..ae9132f8b --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/WithPagination.kt @@ -0,0 +1,51 @@ +package com.atls.hyperion.ui.components.carousel + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.carousel.style.shape.CarouselShape +import com.atls.hyperion.ui.components.carousel.style.shape.default +import com.atls.hyperion.ui.components.pagination.Pagination +import com.atls.hyperion.ui.components.pagination.style.appearance.PaginationAppearance +import com.atls.hyperion.ui.components.pagination.style.appearance.default +import com.atls.hyperion.ui.components.pagination.style.shape.PaginationShape +import com.atls.hyperion.ui.components.pagination.style.shape.circle +import com.atls.hyperion.ui.primitives.VerticalSpacer +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun CarouselWithPagination( + modifier: Modifier = Modifier, + pageCount: Int, + shape: CarouselShape = CarouselShape.default(), + pagerState: PagerState = rememberPagerState(pageCount = { + pageCount + }), + paginationAppearance: PaginationAppearance = PaginationAppearance.default(), + paginationShape: PaginationShape = PaginationShape.circle(), + content: @Composable (page: Int) -> Unit +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + Carousel( + pageCount = pageCount, + modifier = modifier, + shape = shape, + pagerState = pagerState, + content = content + ) + + VerticalSpacer(Space.sm) + + Pagination( + currentPage = pagerState.currentPage, + count = pageCount, + appearance = paginationAppearance, + shape = paginationShape + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CalculateDistance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CalculateDistance.kt new file mode 100644 index 000000000..9d1fd5d3a --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CalculateDistance.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.carousel.lib + +import kotlin.math.abs + +fun calculateDistance(itemCenter: Int, viewportCenter: Int, stepPx: Float): Float = + abs(itemCenter - viewportCenter) / stepPx diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfItem.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfItem.kt new file mode 100644 index 000000000..b722da301 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfItem.kt @@ -0,0 +1,4 @@ +package com.atls.hyperion.ui.components.carousel.lib + +fun centerOfItem(offset: Int, size: Int): Int = + offset + size / 2 diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfViewport.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfViewport.kt new file mode 100644 index 000000000..ea6de18d7 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/CenterOfViewport.kt @@ -0,0 +1,4 @@ +package com.atls.hyperion.ui.components.carousel.lib + +fun centerOfViewport(viewportStartOffset: Int, viewportWidth: Int): Int = + viewportStartOffset + viewportWidth / 2 diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/NormalizedStartIndex.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/NormalizedStartIndex.kt new file mode 100644 index 000000000..584701b53 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/lib/NormalizedStartIndex.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.carousel.lib + +fun normalizedStartIndex(centerIndex: Int, itemsSize: Int): Int { + val middle = Int.MAX_VALUE / 2 + return middle - (middle % itemsSize) + (centerIndex % itemsSize) +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Component.kt new file mode 100644 index 000000000..6e9e41c3e --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Component.kt @@ -0,0 +1,23 @@ +package com.atls.hyperion.ui.components.carousel.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample + +class CarouselStory : ComponentExample { + override val name: String = "Carousel" + + @Composable + override fun Content() { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()) + ) { + DefaultCarouselVariants() + CarouselWithPaginationVariants() + InfiniteOverlayCarouselVariants() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Default.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Default.kt new file mode 100644 index 000000000..d0eed23b4 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/Default.kt @@ -0,0 +1,46 @@ +package com.atls.hyperion.ui.components.carousel.stories + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.carousel.Carousel +import com.atls.hyperion.ui.components.carousel.style.shape.CarouselShape +import com.atls.hyperion.ui.components.carousel.style.shape.default +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun DefaultCarouselVariants() { + ComponentVariants( + name = "Carousel", + appearances = listOf( + "Default" to { Unit } + ), + shapes = listOf( + "Default" to { CarouselShape.default() } + ) + ) { _, shape -> + Carousel( + pageCount = 5, + shape = shape, + modifier = Modifier.height(Space.xl3) + ) { page: Int -> + CarouselItem(page) + } + } +} + +@Composable +private fun CarouselItem(page: Int) { + androidx.compose.foundation.layout.Box( + modifier = Modifier + .fillMaxWidth() + .height(Space.xl3) + .background(if (page % 2 == 0) androidx.compose.ui.graphics.Color.LightGray else androidx.compose.ui.graphics.Color.Gray), + contentAlignment = androidx.compose.ui.Alignment.Center + ) { + androidx.compose.material.Text(text = "Page $page") + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/InfiniteOverlay.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/InfiniteOverlay.kt new file mode 100644 index 000000000..096a5aa05 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/InfiniteOverlay.kt @@ -0,0 +1,52 @@ +package com.atls.hyperion.ui.components.carousel.stories + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.carousel.InfiniteOverlayCarousel +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun InfiniteOverlayCarouselVariants() { + val centerIndexState = remember { mutableStateOf(0) } + ComponentVariants( + name = "Infinite Overlay Carousel", + appearances = listOf( + "Default" to { Unit } + ), + shapes = listOf( + "Default" to { Unit } + ) + ) { _, _ -> + InfiniteOverlayCarousel( + items = listOf(Color.Red, Color.Green, Color.Blue, Color.Yellow, Color.Cyan), + baseCardSize = Space.xl3, + sizeStep = Space.lg, + visibleItemCount = 3, + alphaStep = 0.2f, + minAlpha = 0.5f, + centerIndexState = centerIndexState, + modifier = Modifier.fillMaxWidth().height(Space.xl3) + ) { color, size, alpha, _ -> + Box( + modifier = Modifier + .height(size) + .fillMaxWidth() + .padding(horizontal = Space.sm) + .background(color.copy(alpha = alpha)), + contentAlignment = Alignment.Center + ) { + androidx.compose.material.Text("Item", color = Color.White) + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/WithPagination.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/WithPagination.kt new file mode 100644 index 000000000..753f18bb0 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/stories/WithPagination.kt @@ -0,0 +1,49 @@ +package com.atls.hyperion.ui.components.carousel.stories + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.carousel.CarouselWithPagination +import com.atls.hyperion.ui.components.pagination.style.appearance.PaginationAppearance +import com.atls.hyperion.ui.components.pagination.style.appearance.default +import com.atls.hyperion.ui.components.pagination.style.shape.PaginationShape +import com.atls.hyperion.ui.components.pagination.style.shape.circle +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun CarouselWithPaginationVariants() { + ComponentVariants( + name = "Carousel With Pagination", + appearances = listOf( + "Default" to { PaginationAppearance.default() } + ), + shapes = listOf( + "Circle" to { PaginationShape.circle() } + ) + ) { appearance, shape -> + CarouselWithPagination( + pageCount = 5, + paginationAppearance = appearance, + paginationShape = shape, + modifier = Modifier.height(Space.xl3) + ) { page: Int -> + CarouselItem(page) + } + } +} + +@Composable +private fun CarouselItem(page: Int) { + androidx.compose.foundation.layout.Box( + modifier = Modifier + .fillMaxWidth() + .height(Space.xl3) + .background(if (page % 2 == 0) androidx.compose.ui.graphics.Color.LightGray else androidx.compose.ui.graphics.Color.Gray), + contentAlignment = androidx.compose.ui.Alignment.Center + ) { + androidx.compose.material.Text(text = "Page $page") + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Shape.kt new file mode 100644 index 000000000..f63eb5d40 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Shape.kt @@ -0,0 +1,13 @@ +package com.atls.hyperion.ui.components.carousel.style.shape + +import androidx.compose.runtime.Immutable +import androidx.compose.ui.unit.Dp + +@Immutable +data class CarouselShape( + val itemSpacing: Dp, + val peekWidth: Dp, + val padding: Dp +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Variants.kt new file mode 100644 index 000000000..0fc9152ee --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/carousel/style/shape/Variants.kt @@ -0,0 +1,10 @@ +package com.atls.hyperion.ui.components.carousel.style.shape + +import com.atls.hyperion.ui.theme.tokens.layout.Space + +fun CarouselShape.Companion.default() = + CarouselShape( + itemSpacing = Space.lg, + peekWidth = Space.zero, + padding = Space.xl3 + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/stories/Component.kt index 53ceb1ba2..95012db0b 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/stories/Component.kt @@ -42,13 +42,13 @@ class CheckboxStory : ComponentExample { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = Space.g12) + .padding(horizontal = Space.sm) ) { Text(modifier = Modifier.weight(Weight.full), text = "Enabled") - HorizontalSpacer(Space.g12) + HorizontalSpacer(Space.sm) Switch(checked = enabled, onCheckedChange = { enabled = it }) } - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) ComponentVariants( name = "Checkbox", diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/styles/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/styles/shape/Shape.kt index 382b03759..644b1d526 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/styles/shape/Shape.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/checkbox/styles/shape/Shape.kt @@ -8,7 +8,7 @@ data class CheckboxShape( val size: Dp, val cornerRadius: Dp, val borderStroke: Dp, - val padding: PaddingValues = PaddingValues(Space.g2) + val padding: PaddingValues = PaddingValues(Space.xs5) ) { companion object } diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/DividerStory.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/Component.kt similarity index 93% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/DividerStory.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/Component.kt index fec542066..4b89c4468 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/DividerStory.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/divider/stories/Component.kt @@ -21,7 +21,7 @@ class DividerStory : ComponentExample { @Composable override fun Content() { - Column(modifier = Modifier.padding(Space.g12)) { + Column(modifier = Modifier.padding(Space.sm)) { ComponentVariants( name = "Horizontal Divider", appearances = listOf( @@ -37,7 +37,7 @@ class DividerStory : ComponentExample { ) } - VerticalSpacer(Space.g24) + VerticalSpacer(Space.xl3) ComponentVariants( name = "Vertical Divider", @@ -49,7 +49,7 @@ class DividerStory : ComponentExample { ) ) { appearance: DividerAppearance, shape: DividerShape -> VerticalDivider( - modifier = Modifier.height(Space.g24), + modifier = Modifier.height(Space.xl3), appearance = appearance, shape = shape ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/Input.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/Component.kt similarity index 100% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/Input.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/Component.kt diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/stories/Component.kt index e2ee2c9f0..f595e7490 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/stories/Component.kt @@ -42,25 +42,25 @@ class InputStory : ComponentExample { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = Space.g12), + .padding(horizontal = Space.sm), verticalAlignment = Alignment.CenterVertically ) { Text(modifier = Modifier.weight(Weight.full), text = "Enabled") - HorizontalSpacer(Space.g12) + HorizontalSpacer(Space.sm) Switch(checked = enabled, onCheckedChange = { enabled = it }) } - VerticalSpacer(Space.g8) + VerticalSpacer(Space.xs2) Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = Space.g12), + .padding(horizontal = Space.sm), verticalAlignment = Alignment.CenterVertically ) { Text(modifier = Modifier.weight(Weight.full), text = "Error") - HorizontalSpacer(Space.g12) + HorizontalSpacer(Space.sm) Switch(checked = isError, onCheckedChange = { isError = it }) } - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) ComponentVariants( name = "Input", diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/style/shape/Variants.kt index 504233cea..d905a784e 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/style/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/input/style/shape/Variants.kt @@ -14,8 +14,8 @@ fun InputShape.Companion.large(): InputShape = cornerRadius = CornerRadius.md, borderStroke = BorderStroke.tiny, paddings = PaddingValues( - vertical = Space.g12, - horizontal = Space.g16 + vertical = Space.sm, + horizontal = Space.lg ), textPaddings = PaddingValues(Space.zero), typography = TextStyle(fontSize = FontSize.md) @@ -27,11 +27,11 @@ fun InputShape.Companion.normal(): InputShape = cornerRadius = CornerRadius.xs3, borderStroke = BorderStroke.tiny, paddings = PaddingValues( - vertical = Space.g8, - horizontal = Space.g12 + vertical = Space.xs2, + horizontal = Space.sm ), textPaddings = PaddingValues( - vertical = Space.g4, + vertical = Space.xs4, horizontal = Space.zero ), typography = TextStyle(fontSize = FontSize.sm) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/FlowSelectable.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/FlowSelectable.kt new file mode 100644 index 000000000..15fd029e0 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/FlowSelectable.kt @@ -0,0 +1,43 @@ +package com.atls.hyperion.ui.components.list + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.list.model.SelectionState +import com.atls.hyperion.ui.components.list.style.appearance.ListAppearance +import com.atls.hyperion.ui.components.list.style.appearance.default +import com.atls.hyperion.ui.components.list.style.shape.ListShape +import com.atls.hyperion.ui.components.list.style.shape.flowRow + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun FlowSelectableList( + modifier: Modifier = Modifier, + items: List Unit, isSelected: Boolean) -> Unit>>, + selectionState: SelectionState, + onItemClick: (ID) -> Unit, + appearance: ListAppearance = ListAppearance.default(), + shape: ListShape = ListShape.flowRow() +) { + FlowRow( + modifier = modifier + .fillMaxWidth() + .background(appearance.backgroundColor) + .padding(shape.paddings), + verticalArrangement = Arrangement.spacedBy(shape.spacing), + horizontalArrangement = Arrangement.spacedBy(shape.spacing) + ) { + items.forEach { (id, itemContent) -> + val isSelected = selectionState.isSelected(id) + itemContent( + { onItemClick(id) }, + isSelected + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Selectable.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Selectable.kt new file mode 100644 index 000000000..f9a10c7d4 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Selectable.kt @@ -0,0 +1,37 @@ +package com.atls.hyperion.ui.components.list + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.list.model.SelectionState +import com.atls.hyperion.ui.components.list.style.appearance.ListAppearance +import com.atls.hyperion.ui.components.list.style.appearance.default +import com.atls.hyperion.ui.components.list.style.shape.ListShape +import com.atls.hyperion.ui.components.list.style.shape.flowRow +import com.atls.hyperion.ui.primitives.VerticalSpacer + +@Composable +fun SelectableList( + modifier: Modifier = Modifier, + items: List Unit, isSelected: Boolean) -> Unit>>, + selectionState: SelectionState, + onItemClick: (ID) -> Unit, + appearance: ListAppearance = ListAppearance.default(), + shape: ListShape = ListShape.flowRow() +) { + Column( + modifier = modifier + .fillMaxWidth() + .background(color = appearance.backgroundColor) + .padding(shape.paddings) + ) { + items.forEach { (id, itemContent) -> + val isSelected = selectionState.isSelected(id) + itemContent({ onItemClick(id) }, isSelected) + VerticalSpacer(shape.spacing) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Vertical.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Vertical.kt new file mode 100644 index 000000000..f50117ba7 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/Vertical.kt @@ -0,0 +1,27 @@ +package com.atls.hyperion.ui.components.list + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun VerticalList( + items: List, + modifier: Modifier = Modifier, + arrangement: Arrangement.Vertical = Arrangement.Top, + contentPadding: PaddingValues = PaddingValues(), + itemContent: @Composable (T) -> Unit +) { + LazyColumn( + modifier = modifier, + verticalArrangement = arrangement, + contentPadding = contentPadding + ) { + items(items) { item -> + itemContent(item) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/Text.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/Text.kt new file mode 100644 index 000000000..877cff636 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/Text.kt @@ -0,0 +1,63 @@ +package com.atls.hyperion.ui.components.list.item + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.list.item.model.ListItemState +import com.atls.hyperion.ui.components.list.item.style.appearance.TextListItemAppearance +import com.atls.hyperion.ui.components.list.item.style.appearance.default +import com.atls.hyperion.ui.components.list.item.style.shape.TextListItemShape +import com.atls.hyperion.ui.components.list.item.style.shape.default +import com.atls.hyperion.ui.primitives.Text +import com.atls.hyperion.ui.shared.addon.AddonPosition.After +import com.atls.hyperion.ui.shared.addon.AddonPosition.Before +import com.atls.hyperion.ui.shared.addon.AddonSlotManager +import com.atls.hyperion.ui.theme.tokens.layout.Weight + +@Composable +fun TextListItem( + modifier: Modifier = Modifier, + text: String, + state: ListItemState, + onClick: () -> Unit, + addons: AddonSlotManager = AddonSlotManager(), + appearance: TextListItemAppearance = TextListItemAppearance.default(), + shape: TextListItemShape = TextListItemShape.default() +) { + val colors = appearance.fromState(state) + + Row( + modifier = modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .background( + color = colors.backgroundColor, + shape = RoundedCornerShape(shape.cornerRadius) + ) + .padding(shape.paddings) + ) { + addons.get(Before).forEach { + it.Content() + it.Spacer() + } + + Text( + modifier = Modifier + .weight(Weight.full) + .padding(shape.textPaddings), + text = text, + textAlign = shape.textAlign, + color = colors.textColor, + typography = shape.typography + ) + addons.get(After).forEach { + it.Spacer() + it.Content() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/model/State.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/model/State.kt new file mode 100644 index 000000000..6c8ca6011 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/model/State.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.list.item.model + +sealed interface ListItemState { + data object Selected: ListItemState + data object Unselected: ListItemState +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Appearance.kt new file mode 100644 index 000000000..168058655 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Appearance.kt @@ -0,0 +1,16 @@ +package com.atls.hyperion.ui.components.list.item.style.appearance + +import com.atls.hyperion.ui.components.list.item.model.ListItemState + +data class TextListItemAppearance( + val selected: TextListItemAppearanceColors, + val unselected: TextListItemAppearanceColors +) { + companion object + + fun fromState(state: ListItemState) = + when (state) { + ListItemState.Selected -> this.selected + ListItemState.Unselected -> this.unselected + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Colors.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Colors.kt new file mode 100644 index 000000000..6e42f2675 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Colors.kt @@ -0,0 +1,8 @@ +package com.atls.hyperion.ui.components.list.item.style.appearance + +import androidx.compose.ui.graphics.Color + +data class TextListItemAppearanceColors( + val backgroundColor: Color, + val textColor: Color +) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Variants.kt new file mode 100644 index 000000000..618e9fb92 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/appearance/Variants.kt @@ -0,0 +1,17 @@ +package com.atls.hyperion.ui.components.list.item.style.appearance + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +@Composable +fun TextListItemAppearance.Companion.default(): TextListItemAppearance = + TextListItemAppearance( + selected = TextListItemAppearanceColors( + backgroundColor = Colors.Palette.blueProtective, + textColor = Colors.Text.white + ), + unselected = TextListItemAppearanceColors( + backgroundColor = Colors.Palette.white, + textColor = Colors.Text.black + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Shape.kt new file mode 100644 index 000000000..dbaa1e4cf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Shape.kt @@ -0,0 +1,16 @@ +package com.atls.hyperion.ui.components.list.item.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp + +class TextListItemShape( + val cornerRadius: Dp, + val paddings: PaddingValues, + val textPaddings: PaddingValues, + val typography: TextStyle, + val textAlign: TextAlign +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Variants.kt new file mode 100644 index 000000000..8fa97acfa --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/item/style/shape/Variants.kt @@ -0,0 +1,31 @@ +package com.atls.hyperion.ui.components.list.item.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.FontWeight +import com.atls.hyperion.ui.theme.typography.NunitoSansFontFamily + +@Composable +fun TextListItemShape.Companion.default(): TextListItemShape = + TextListItemShape( + cornerRadius = CornerRadius.xl2, + paddings = PaddingValues( + horizontal = Space.sm, + vertical = Space.xs2 + ), + textPaddings = PaddingValues( + horizontal = Space.xs4, + vertical = Space.zero + ), + typography = TextStyle( + fontSize = FontSize.xs, + fontWeight = FontWeight.medium, + fontFamily = NunitoSansFontFamily() + ), + textAlign = TextAlign.Start + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/model/SelectionState.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/model/SelectionState.kt new file mode 100644 index 000000000..6adc63cc7 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/model/SelectionState.kt @@ -0,0 +1,13 @@ +package com.atls.hyperion.ui.components.list.model + +sealed interface SelectionState { + fun isSelected(item: T): Boolean + + data class Single(val selectedItem: T) : SelectionState { + override fun isSelected(item: T) = item == selectedItem + } + + data class Multiple(val selectedItems: Set) : SelectionState { + override fun isSelected(item: T) = selectedItems.contains(item) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Component.kt new file mode 100644 index 000000000..3696959e2 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Component.kt @@ -0,0 +1,30 @@ +package com.atls.hyperion.ui.components.list.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class ListStories : ComponentExample { + override val name: String = "Lists" + + @Composable + override fun Content() { + Column { + VerticalListVariants() + + Spacer(Modifier.height(Space.md)) + + SelectableListVariants() + + Spacer(Modifier.height(Space.md)) + + FlowSelectableListVariants() + + Spacer(Modifier.height(Space.xl2)) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/FlowSelectable.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/FlowSelectable.kt new file mode 100644 index 000000000..55e0d4fa4 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/FlowSelectable.kt @@ -0,0 +1,63 @@ +package com.atls.hyperion.ui.components.list.stories + +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.list.FlowSelectableList +import com.atls.hyperion.ui.components.list.item.TextListItem +import com.atls.hyperion.ui.components.list.item.model.ListItemState +import com.atls.hyperion.ui.components.list.item.style.appearance.TextListItemAppearance +import com.atls.hyperion.ui.components.list.item.style.appearance.default +import com.atls.hyperion.ui.components.list.item.style.shape.TextListItemShape +import com.atls.hyperion.ui.components.list.item.style.shape.default +import com.atls.hyperion.ui.components.list.model.SelectionState +import com.atls.hyperion.ui.components.list.style.appearance.ListAppearance +import com.atls.hyperion.ui.components.list.style.appearance.default +import com.atls.hyperion.ui.components.list.style.shape.ListShape +import com.atls.hyperion.ui.components.list.style.shape.flowRow + +@Composable +fun FlowSelectableListVariants() { + val flowItems = listOf("Apple", "Banana", "Orange", "Mango", "Peach", "Grapes") + var flowSelectionState by remember { + mutableStateOf>( + SelectionState.Multiple(emptySet()) + ) + } + + ComponentVariants( + name = "FlowSelectableList", + appearances = listOf("Default" to { ListAppearance.default() }), + shapes = listOf("FlowRow" to { ListShape.flowRow() }) + ) { appearance, shape -> + FlowSelectableList( + items = flowItems.map { id -> + id to @Composable { onClick: () -> Unit, isSelected: Boolean -> + TextListItem( + modifier = Modifier.width(IntrinsicSize.Min), + text = id, + state = if (isSelected) ListItemState.Selected else ListItemState.Unselected, + onClick = onClick, + appearance = TextListItemAppearance.default(), + shape = TextListItemShape.default() + ) + } + }, + selectionState = flowSelectionState, + onItemClick = { id -> + val current = + (flowSelectionState as SelectionState.Multiple).selectedItems.toMutableSet() + if (current.contains(id)) current.remove(id) else current.add(id) + flowSelectionState = SelectionState.Multiple(current) + }, + appearance = appearance, + shape = shape + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Selectable.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Selectable.kt new file mode 100644 index 000000000..066bc7ee9 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Selectable.kt @@ -0,0 +1,60 @@ +package com.atls.hyperion.ui.components.list.stories + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.list.SelectableList +import com.atls.hyperion.ui.components.list.item.TextListItem +import com.atls.hyperion.ui.components.list.item.model.ListItemState +import com.atls.hyperion.ui.components.list.item.style.appearance.TextListItemAppearance +import com.atls.hyperion.ui.components.list.item.style.appearance.default +import com.atls.hyperion.ui.components.list.item.style.shape.TextListItemShape +import com.atls.hyperion.ui.components.list.item.style.shape.default +import com.atls.hyperion.ui.components.list.model.SelectionState +import com.atls.hyperion.ui.components.list.style.appearance.ListAppearance +import com.atls.hyperion.ui.components.list.style.appearance.default +import com.atls.hyperion.ui.components.list.style.shape.ListShape +import com.atls.hyperion.ui.components.list.style.shape.flowRow + +@Composable +fun SelectableListVariants() { + val selectableItems = listOf("Item 1", "Item 2") + var selectionState by remember { + mutableStateOf>( + SelectionState.Multiple( + emptySet() + ) + ) + } + ComponentVariants( + name = "SelectableList", + appearances = listOf("Default" to { ListAppearance.default() }), + shapes = listOf("FlowRow" to { ListShape.flowRow() }) + ) { appearance, shape -> + SelectableList( + items = selectableItems.map { id -> + id to @Composable { onClick: () -> Unit, isSelected: Boolean -> + TextListItem( + text = id, + state = if (isSelected) ListItemState.Selected else ListItemState.Unselected, + onClick = onClick, + appearance = TextListItemAppearance.default(), + shape = TextListItemShape.default() + ) + } + }, + selectionState = selectionState, + onItemClick = { id -> + val current = + (selectionState as SelectionState.Multiple).selectedItems.toMutableSet() + if (current.contains(id)) current.remove(id) else current.add(id) + selectionState = SelectionState.Multiple(current) + }, + appearance = appearance, + shape = shape + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Vertical.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Vertical.kt new file mode 100644 index 000000000..c9fe40059 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/stories/Vertical.kt @@ -0,0 +1,37 @@ +package com.atls.hyperion.ui.components.list.stories + +import androidx.compose.runtime.Composable +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.list.VerticalList +import com.atls.hyperion.ui.components.list.item.TextListItem +import com.atls.hyperion.ui.components.list.item.model.ListItemState +import com.atls.hyperion.ui.components.list.item.style.appearance.TextListItemAppearance +import com.atls.hyperion.ui.components.list.item.style.appearance.default +import com.atls.hyperion.ui.components.list.item.style.shape.TextListItemShape +import com.atls.hyperion.ui.components.list.item.style.shape.default +import com.atls.hyperion.ui.components.list.style.appearance.ListAppearance +import com.atls.hyperion.ui.components.list.style.appearance.default +import com.atls.hyperion.ui.components.list.style.shape.ListShape +import com.atls.hyperion.ui.components.list.style.shape.flowRow +import com.atls.hyperion.ui.primitives.VerticalSpacer + +@Composable +fun VerticalListVariants() { + val simpleItems = listOf("Item A", "Item B", "Item C") + ComponentVariants( + name = "VerticalList", + appearances = listOf("Default" to { ListAppearance.default() }), + shapes = listOf("Default" to { ListShape.flowRow() }) + ) { appearance, shape -> + VerticalList(items = simpleItems) { item -> + TextListItem( + text = item, + state = ListItemState.Unselected, + onClick = {}, + appearance = TextListItemAppearance.default(), + shape = TextListItemShape.default() + ) + VerticalSpacer(shape.spacing) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Appearance.kt new file mode 100644 index 000000000..e41cc6a72 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Appearance.kt @@ -0,0 +1,9 @@ +package com.atls.hyperion.ui.components.list.style.appearance + +import androidx.compose.ui.graphics.Color + +data class ListAppearance( + val backgroundColor: Color +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Variants.kt new file mode 100644 index 000000000..7ace05974 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/appearance/Variants.kt @@ -0,0 +1,10 @@ +package com.atls.hyperion.ui.components.list.style.appearance + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +@Composable +fun ListAppearance.Companion.default(): ListAppearance = + ListAppearance( + backgroundColor = Colors.Palette.transparent + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Shape.kt new file mode 100644 index 000000000..222ca49cf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Shape.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.list.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.unit.Dp + +data class ListShape( + val paddings: PaddingValues, + val spacing: Dp +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Variants.kt new file mode 100644 index 000000000..541dd58bd --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/list/style/shape/Variants.kt @@ -0,0 +1,19 @@ +package com.atls.hyperion.ui.components.list.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun ListShape.Companion.default(): ListShape = + ListShape( + paddings = PaddingValues(Space.zero), + spacing = Space.zero + ) + +@Composable +fun ListShape.Companion.flowRow(): ListShape = + ListShape( + paddings = PaddingValues(Space.zero), + spacing = Space.sm + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/dragHandle/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/dragHandle/style/shape/Variants.kt index ed2d95e21..357f8f59d 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/dragHandle/style/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/dragHandle/style/shape/Variants.kt @@ -12,5 +12,5 @@ fun DragHandleShape.Companion.default(): DragHandleShape = height = DragHandleSize.height, width = DragHandleSize.width, cornerRadius = CornerRadius.xl6, - paddings = PaddingValues(top = Space.g8) + paddings = PaddingValues(top = Space.xs2) ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/stories/Component.kt index 8ce2156a5..8bb61c140 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/bottom/stories/Component.kt @@ -36,7 +36,7 @@ class BottomDialogStory : ComponentExample { Column( modifier = Modifier .fillMaxWidth() - .padding(Space.g12) + .padding(Space.sm) ) { Button( text = "Show Bottom Dialog", @@ -53,11 +53,11 @@ class BottomDialogStory : ComponentExample { Column( modifier = Modifier .fillMaxWidth() - .padding(Space.g16) + .padding(Space.lg) ) { Text(text = "This is a Bottom Dialog") Button( - modifier = Modifier.padding(top = Space.g12), + modifier = Modifier.padding(top = Space.sm), text = "Close", appearance = ButtonAppearance.blue(), shape = ButtonShape.normal(), diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/Popup.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/Component.kt similarity index 100% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/Popup.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/Component.kt diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/stories/Component.kt index 378158877..3d24bb26e 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/popup/stories/Component.kt @@ -29,7 +29,7 @@ class PopupStory : ComponentExample { Column( modifier = Modifier .fillMaxWidth() - .padding(Space.g12) + .padding(Space.sm) ) { Button( text = "Show Popup", @@ -45,11 +45,11 @@ class PopupStory : ComponentExample { Column( modifier = Modifier .fillMaxWidth() - .padding(Space.g16) + .padding(Space.lg) ) { Text(text = "This is a Popup Dialog") Button( - modifier = Modifier.padding(top = Space.g12), + modifier = Modifier.padding(top = Space.sm), text = "Close", appearance = ButtonAppearance.blue(), shape = ButtonShape.normal(), diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/style/shape/Variants.kt index dd33044dc..92fb3c5f9 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/style/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/modal/style/shape/Variants.kt @@ -12,8 +12,8 @@ fun ModalShape.Companion.popup(): ModalShape = ModalShape( shape = RoundedCornerShape(CornerRadius.zero), shadowElevation = Elevation.tiny, - paddings = PaddingValues(Space.g20), - spacers = PaddingValues(horizontal = Space.g24) + paddings = PaddingValues(Space.xl), + spacers = PaddingValues(horizontal = Space.xl3) ) @Composable @@ -25,10 +25,10 @@ fun ModalShape.Companion.bottom(): ModalShape = ), shadowElevation = Elevation.zero, paddings = PaddingValues( - top = Space.g4, - bottom = Space.g20, - start = Space.g20, - end = Space.g20 + top = Space.xs4, + bottom = Space.xl, + start = Space.xl, + end = Space.xl ), spacers = PaddingValues(horizontal = Space.zero) ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/Component.kt new file mode 100644 index 000000000..50262af4a --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/Component.kt @@ -0,0 +1,44 @@ +package com.atls.hyperion.ui.components.pagination + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.pagination.state.PaginationState +import com.atls.hyperion.ui.components.pagination.style.appearance.PaginationAppearance +import com.atls.hyperion.ui.components.pagination.style.shape.PaginationShape +import com.atls.hyperion.ui.components.pagination.ui.PaginationItem + +@Composable +fun Pagination( + currentPage: Int, + count: Int, + appearance: PaginationAppearance, + shape: PaginationShape, + modifier: Modifier = Modifier, + onPageClick: ((Int) -> Unit)? = null +) { + Row( + horizontalArrangement = Arrangement.spacedBy(shape.spacing), + verticalAlignment = Alignment.CenterVertically, + modifier = modifier.background(appearance.backgroundColor) + ) { + for (index in 0 until count) { + val state = when { + index == currentPage -> PaginationState.Active + else -> PaginationState.Disabled + } + val itemColor = appearance.fromState(state) + val itemSize = shape.sizeFromState(state) + + PaginationItem( + itemColor = itemColor, + size = itemSize, + cornerRadius = shape.cornerRadius, + onClick = onPageClick?.let { { it(index) } } + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/state/State.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/state/State.kt new file mode 100644 index 000000000..dff1fc2e1 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/state/State.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.pagination.state + +enum class PaginationState { + Active, + Disabled +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Carousel.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Carousel.kt new file mode 100644 index 000000000..f7e3df103 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Carousel.kt @@ -0,0 +1,50 @@ +package com.atls.hyperion.ui.components.pagination.stories + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.carousel.CarouselWithPagination +import com.atls.hyperion.ui.components.pagination.style.appearance.PaginationAppearance +import com.atls.hyperion.ui.components.pagination.style.appearance.default +import com.atls.hyperion.ui.components.pagination.style.shape.PaginationShape +import com.atls.hyperion.ui.components.pagination.style.shape.circle +import com.atls.hyperion.ui.components.pagination.style.shape.rectangle +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun CarouselPaginationVariants() { + ComponentVariants( + name = "Pagination with Carousel", + appearances = listOf( + "Default" to { PaginationAppearance.default() } + ), + shapes = listOf( + "Circle" to { PaginationShape.circle() }, + "Rectangle" to { PaginationShape.rectangle() } + ) + ) { appearance, shape -> + CarouselWithPagination( + pageCount = 5, + paginationAppearance = appearance, + paginationShape = shape, + modifier = Modifier.height(Space.xl3) + ) { page -> + Box( + modifier = Modifier + .fillMaxWidth() + .height(Space.xl3) + .background(if (page % 2 == 0) Color.LightGray else Color.Gray), + contentAlignment = Alignment.Center + ) { + Text(text = "Page $page") + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/ClickablePagination.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/ClickablePagination.kt new file mode 100644 index 000000000..a8bf398fa --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/ClickablePagination.kt @@ -0,0 +1,38 @@ +package com.atls.hyperion.ui.components.pagination.stories + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.pagination.Pagination +import com.atls.hyperion.ui.components.pagination.style.appearance.PaginationAppearance +import com.atls.hyperion.ui.components.pagination.style.appearance.default +import com.atls.hyperion.ui.components.pagination.style.shape.PaginationShape +import com.atls.hyperion.ui.components.pagination.style.shape.circle +import com.atls.hyperion.ui.components.pagination.style.shape.rectangle + +@Composable +fun ClickablePaginationVariants() { + var currentPage by remember { mutableStateOf(1) } + + ComponentVariants( + name = "Pagination (Clickable)", + appearances = listOf( + "Default" to { PaginationAppearance.default() } + ), + shapes = listOf( + "Circle" to { PaginationShape.circle() }, + "Rectangle" to { PaginationShape.rectangle() } + ) + ) { appearance: PaginationAppearance, shape: PaginationShape -> + Pagination( + currentPage = currentPage, + count = 5, + appearance = appearance, + shape = shape, + onPageClick = { currentPage = it } + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Component.kt new file mode 100644 index 000000000..7188b8ceb --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/stories/Component.kt @@ -0,0 +1,22 @@ +package com.atls.hyperion.ui.components.pagination.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.primitives.VerticalSpacer +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class PaginationStory : ComponentExample { + override val name: String = "Pagination" + + @Composable + override fun Content() { + Column { + ClickablePaginationVariants() + + VerticalSpacer(Space.xl3) + + CarouselPaginationVariants() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/Size.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/Size.kt new file mode 100644 index 000000000..b53143dbf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/Size.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.pagination.style + +import androidx.compose.ui.unit.dp + +object PaginationItemSize { + val medium = 12.dp + val small = 8.dp + + val rectangleHeight = 4.dp + val rectangleWidth = 20.dp +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Appearance.kt new file mode 100644 index 000000000..055def21a --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Appearance.kt @@ -0,0 +1,18 @@ +package com.atls.hyperion.ui.components.pagination.style.appearance + +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.ui.components.pagination.state.PaginationState + +data class PaginationAppearance( + val activeColor: Color, + val disabledColor: Color, + val backgroundColor: Color = Color.Transparent +) { + companion object + + fun fromState(state: PaginationState): Color = + when (state) { + PaginationState.Active -> activeColor + PaginationState.Disabled -> disabledColor + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Variants.kt new file mode 100644 index 000000000..a9e81e342 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/appearance/Variants.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.pagination.style.appearance + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +@Composable +fun PaginationAppearance.Companion.default(): PaginationAppearance = + PaginationAppearance( + activeColor = Colors.Palette.blueProtective, + disabledColor = Colors.Palette.gray + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Shape.kt new file mode 100644 index 000000000..3bfd4af58 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Shape.kt @@ -0,0 +1,21 @@ +package com.atls.hyperion.ui.components.pagination.style.shape + +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpSize +import com.atls.hyperion.ui.components.pagination.state.PaginationState + +class PaginationShape( + val activeSize: DpSize, + val disabledSize: DpSize, + val spacing: Dp, + val cornerRadius: Dp +) { + companion object + + fun sizeFromState(state: PaginationState): DpSize = + when (state) { + PaginationState.Active -> activeSize + PaginationState.Disabled -> disabledSize + } +} + diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Variants.kt new file mode 100644 index 000000000..57ead6665 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/style/shape/Variants.kt @@ -0,0 +1,28 @@ +package com.atls.hyperion.ui.components.pagination.style.shape + +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.DpSize +import com.atls.hyperion.ui.components.pagination.style.PaginationItemSize +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun PaginationShape.Companion.circle(): PaginationShape = + PaginationShape( + activeSize = DpSize(PaginationItemSize.medium, PaginationItemSize.medium), + disabledSize = DpSize(PaginationItemSize.small, PaginationItemSize.small), + spacing = Space.lg, + cornerRadius = CornerRadius.full + ) + +@Composable +fun PaginationShape.Companion.rectangle(): PaginationShape = + PaginationShape( + activeSize = DpSize(PaginationItemSize.rectangleWidth, PaginationItemSize.rectangleHeight), + disabledSize = DpSize( + PaginationItemSize.rectangleWidth, + PaginationItemSize.rectangleHeight + ), + spacing = Space.xs2, + cornerRadius = CornerRadius.md + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/ui/Item.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/ui/Item.kt new file mode 100644 index 000000000..5d307272a --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/pagination/ui/Item.kt @@ -0,0 +1,40 @@ +package com.atls.hyperion.ui.components.pagination.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpSize + +@Composable +fun PaginationItem( + itemColor: Color, + size: DpSize, + cornerRadius: Dp, + onClick: (() -> Unit)? = null +) { + Box( + modifier = Modifier + .size(size) + .background( + color = itemColor, + shape = RoundedCornerShape(cornerRadius) + ) + .let { + if (onClick != null) { + it.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = onClick + ) + } else it + } + ) +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/Component.kt new file mode 100644 index 000000000..7679e7ea3 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/Component.kt @@ -0,0 +1,37 @@ +package com.atls.hyperion.ui.components.placeholder + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.placeholder.model.PlaceholderType +import com.atls.hyperion.ui.components.placeholder.styles.appearance.PlaceholderAppearance +import com.atls.hyperion.ui.components.placeholder.styles.appearance.imageBox +import com.atls.hyperion.ui.components.placeholder.styles.shape.PlaceholderShape +import com.atls.hyperion.ui.components.placeholder.ui.PlaceholderLayout + +@Composable +fun Placeholder( + modifier: Modifier = Modifier, + type: PlaceholderType, + appearance: PlaceholderAppearance = PlaceholderAppearance.imageBox(), + shape: PlaceholderShape +) { + when (type) { + is PlaceholderType.Logo -> { + PlaceholderLayout( + modifier = modifier, + appearance = appearance, + shape = shape, + text = type.text, + orientation = type.orientation + ) + } + + PlaceholderType.ImageBox -> { + PlaceholderLayout( + modifier = modifier, + appearance = appearance, + shape = shape + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Orientation.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Orientation.kt new file mode 100644 index 000000000..9b02fd44f --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Orientation.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.placeholder.model + +enum class PlaceholderOrientation { + Horizontal, + Vertical +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Type.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Type.kt new file mode 100644 index 000000000..8d4e11848 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/model/Type.kt @@ -0,0 +1,6 @@ +package com.atls.hyperion.ui.components.placeholder.model + +sealed interface PlaceholderType { + data class Logo(val text: String, val orientation: PlaceholderOrientation) : PlaceholderType + object ImageBox : PlaceholderType +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Component.kt new file mode 100644 index 000000000..3852a3d8d --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Component.kt @@ -0,0 +1,29 @@ +package com.atls.hyperion.ui.components.placeholder.stories + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class PlaceholderStory( + override val name: String = "Placeholder" +) : ComponentExample { + + @Composable + override fun Content() { + Column( + modifier = Modifier + .fillMaxSize() + .padding(Space.md), + verticalArrangement = Arrangement.spacedBy(Space.xl2) + ) { + ImageBoxPlaceholderVariants() + LogoPlaceholderHorizontalVariants() + LogoPlaceholderVerticalVariants() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/ImageBox.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/ImageBox.kt new file mode 100644 index 000000000..1e01c1bba --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/ImageBox.kt @@ -0,0 +1,32 @@ +package com.atls.hyperion.ui.components.placeholder.stories + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.placeholder.Placeholder +import com.atls.hyperion.ui.components.placeholder.model.PlaceholderType +import com.atls.hyperion.ui.components.placeholder.styles.appearance.PlaceholderAppearance +import com.atls.hyperion.ui.components.placeholder.styles.appearance.imageBox +import com.atls.hyperion.ui.components.placeholder.styles.shape.PlaceholderShape +import com.atls.hyperion.ui.components.placeholder.styles.shape.imageBox +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun ImageBoxPlaceholderVariants() { + ComponentVariants( + name = "ImageBoxPlaceholder", + appearances = listOf("Default" to { PlaceholderAppearance.imageBox() }), + shapes = listOf("Default" to { PlaceholderShape.imageBox() }) + ) { appearance, shape -> + Box(modifier = Modifier.size(Space.xl3)) { + Placeholder( + modifier = Modifier.matchParentSize(), + type = PlaceholderType.ImageBox, + appearance = appearance, + shape = shape + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Logo.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Logo.kt new file mode 100644 index 000000000..4b83f58b8 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/stories/Logo.kt @@ -0,0 +1,47 @@ +package com.atls.hyperion.ui.components.placeholder.stories + +import androidx.compose.runtime.Composable +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.placeholder.Placeholder +import com.atls.hyperion.ui.components.placeholder.model.PlaceholderOrientation +import com.atls.hyperion.ui.components.placeholder.model.PlaceholderType +import com.atls.hyperion.ui.components.placeholder.styles.appearance.PlaceholderAppearance +import com.atls.hyperion.ui.components.placeholder.styles.appearance.logo +import com.atls.hyperion.ui.components.placeholder.styles.shape.PlaceholderShape +import com.atls.hyperion.ui.components.placeholder.styles.shape.logo + +@Composable +fun LogoPlaceholderHorizontalVariants() { + ComponentVariants( + name = "LogoPlaceholder Horizontal", + appearances = listOf("Default" to { PlaceholderAppearance.logo() }), + shapes = listOf("Default" to { PlaceholderShape.logo() }) + ) { appearance, shape -> + Placeholder( + type = PlaceholderType.Logo( + text = "Горизонтальный", + orientation = PlaceholderOrientation.Horizontal + ), + appearance = appearance, + shape = shape + ) + } +} + +@Composable +fun LogoPlaceholderVerticalVariants() { + ComponentVariants( + name = "LogoPlaceholder Vertical", + appearances = listOf("Default" to { PlaceholderAppearance.logo() }), + shapes = listOf("Default" to { PlaceholderShape.logo() }) + ) { appearance, shape -> + Placeholder( + type = PlaceholderType.Logo( + text = "Вертикальный", + orientation = PlaceholderOrientation.Vertical + ), + appearance = appearance, + shape = shape + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Appearance.kt new file mode 100644 index 000000000..a1ad44431 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Appearance.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.placeholder.styles.appearance + +import androidx.compose.ui.graphics.Color + +data class PlaceholderAppearance( + val backgroundColor: Color, + val iconColor: Color, + val textColor: Color +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Variants.kt new file mode 100644 index 000000000..68e98f125 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/appearance/Variants.kt @@ -0,0 +1,18 @@ +package com.atls.hyperion.ui.components.placeholder.styles.appearance + +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +fun PlaceholderAppearance.Companion.imageBox(): PlaceholderAppearance = + PlaceholderAppearance( + backgroundColor = Colors.Palette.lightPurple, + iconColor = Colors.Text.darkGray, + textColor = Colors.Text.black + + ) + +fun PlaceholderAppearance.Companion.logo(): PlaceholderAppearance = + PlaceholderAppearance( + backgroundColor = Colors.Palette.transparent, + iconColor = Colors.Text.black, + textColor = Colors.Text.black + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Shape.kt new file mode 100644 index 000000000..766a22d21 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Shape.kt @@ -0,0 +1,12 @@ +package com.atls.hyperion.ui.components.placeholder.styles.shape + +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.Dp + +data class PlaceholderShape( + val iconSize: Dp, + val typography: TextStyle, + val spacing: Dp +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Variants.kt new file mode 100644 index 000000000..ebc846c27 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/styles/shape/Variants.kt @@ -0,0 +1,33 @@ +package com.atls.hyperion.ui.components.placeholder.styles.shape + +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import com.atls.hyperion.ui.primitives.icon.IconSize +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.FontWeight +import com.atls.hyperion.ui.theme.typography.NunitoSansFontFamily + +@Composable +fun PlaceholderShape.Companion.imageBox(): PlaceholderShape = + PlaceholderShape( + iconSize = IconSize.large, + typography = TextStyle( + fontFamily = NunitoSansFontFamily(), + fontWeight = FontWeight.bold, + fontSize = FontSize.xl + ), + spacing = Space.xs2 + ) + +@Composable +fun PlaceholderShape.Companion.logo(): PlaceholderShape = + PlaceholderShape( + iconSize = IconSize.large, + typography = TextStyle( + fontFamily = NunitoSansFontFamily(), + fontWeight = FontWeight.bold, + fontSize = FontSize.xl + ), + spacing = Space.xs2 + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/ui/Layout.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/ui/Layout.kt new file mode 100644 index 000000000..0b6f071d0 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/placeholder/ui/Layout.kt @@ -0,0 +1,79 @@ +package com.atls.hyperion.ui.components.placeholder.ui + +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.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.components.placeholder.model.PlaceholderOrientation +import com.atls.hyperion.ui.components.placeholder.styles.appearance.PlaceholderAppearance +import com.atls.hyperion.ui.components.placeholder.styles.shape.PlaceholderShape +import com.atls.hyperion.ui.generated.resources.Res +import com.atls.hyperion.ui.generated.resources.placeholder +import com.atls.hyperion.ui.primitives.icon.Icon +import org.jetbrains.compose.resources.painterResource + +@Composable +fun PlaceholderLayout( + modifier: Modifier = Modifier, + appearance: PlaceholderAppearance, + shape: PlaceholderShape, + text: String? = null, + orientation: PlaceholderOrientation = PlaceholderOrientation.Horizontal, + content: @Composable () -> Unit = { + Icon( + icon = painterResource(Res.drawable.placeholder), + color = appearance.iconColor, + size = shape.iconSize + ) + } +) { + Box( + modifier = modifier + .background(appearance.backgroundColor), + contentAlignment = Alignment.Center + ) { + if (text == null) { + content() + } else { + when (orientation) { + PlaceholderOrientation.Horizontal -> { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + content() + Spacer(modifier = Modifier.width(shape.spacing)) + Text( + text = text, + style = shape.typography, + color = appearance.textColor + ) + } + } + + PlaceholderOrientation.Vertical -> { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + content() + Spacer(modifier = Modifier.height(shape.spacing)) + Text( + text = text, + style = shape.typography, + color = appearance.textColor + ) + } + } + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Circle.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Circle.kt new file mode 100644 index 000000000..7b9eae219 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Circle.kt @@ -0,0 +1,101 @@ +package com.atls.hyperion.ui.components.progress + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.drawscope.Stroke +import com.atls.hyperion.ui.components.progress.config.DEFAULT_CANVAS_SCALE +import com.atls.hyperion.ui.components.progress.config.DEFAULT_GAP_DEGREE +import com.atls.hyperion.ui.components.progress.config.FULL_CIRCLE +import com.atls.hyperion.ui.components.progress.config.GAP_BOTTOM_OFFSET +import com.atls.hyperion.ui.components.progress.config.GAP_LEFT_OFFSET +import com.atls.hyperion.ui.components.progress.config.GAP_RIGHT_OFFSET +import com.atls.hyperion.ui.components.progress.config.GAP_TOP_OFFSET +import com.atls.hyperion.ui.components.progress.config.MAX_PERCENT +import com.atls.hyperion.ui.components.progress.config.MIN_PERCENT +import com.atls.hyperion.ui.components.progress.lib.getBrush +import com.atls.hyperion.ui.components.progress.lib.getSolidColor +import com.atls.hyperion.ui.components.progress.model.GapPosition +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.appearance.primary +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default + +@Composable +fun CircleProgress( + percents: List, + modifier: Modifier = Modifier, + appearance: ProgressAppearance = ProgressAppearance.primary(), + shape: ProgressShape = ProgressShape.default(), + gapDegree: Float = DEFAULT_GAP_DEGREE, + gapPosition: GapPosition = GapPosition.Top +) { + Canvas(modifier = modifier.size(shape.strokeWidth * DEFAULT_CANVAS_SCALE)) { + val strokeWidth = shape.strokeWidth.toPx() + val trailWidth = shape.trailWidth.toPx() + val diameter = size.minDimension - maxOf(strokeWidth, trailWidth) + val topLeft = Offset((size.width - diameter) / 2, (size.height - diameter) / 2) + val totalSweep = FULL_CIRCLE - gapDegree + + val startOffset = when (gapPosition) { + GapPosition.Top -> GAP_TOP_OFFSET + gapDegree / 2 + GapPosition.Bottom -> GAP_BOTTOM_OFFSET + gapDegree / 2 + GapPosition.Left -> GAP_LEFT_OFFSET + gapDegree / 2 + GapPosition.Right -> GAP_RIGHT_OFFSET + gapDegree / 2 + } + + drawArc( + color = appearance.colors.trailColor, + startAngle = startOffset, + sweepAngle = totalSweep, + useCenter = false, + topLeft = topLeft, + size = Size(diameter, diameter), + style = Stroke(width = trailWidth, cap = shape.trailLinecap) + ) + + var currentStart = startOffset + percents.forEachIndexed { index, percent -> + val sweep = if (percent >= 100f) totalSweep else ( + percent.coerceIn(MIN_PERCENT, MAX_PERCENT) / MAX_PERCENT) * totalSweep + if (sweep <= 0f) return@forEachIndexed + + val brush = getBrush(appearance.colors, index) + if (brush != null) { + drawArc( + brush = brush, + startAngle = currentStart, + sweepAngle = sweep, + useCenter = false, + topLeft = topLeft, + size = Size(diameter, diameter), + style = Stroke(width = strokeWidth, cap = shape.strokeLinecap) + ) + } else { + drawArc( + color = getSolidColor(appearance.colors, index), + startAngle = currentStart, + sweepAngle = sweep, + useCenter = false, + topLeft = topLeft, + size = Size(diameter, diameter), + style = Stroke(width = strokeWidth, cap = shape.strokeLinecap) + ) + } + currentStart += sweep + } + } +} + +@Composable +fun CircleProgress( + percent: Float, + modifier: Modifier = Modifier, + appearance: ProgressAppearance = ProgressAppearance.primary(), + shape: ProgressShape = ProgressShape.default(), + gapDegree: Float = 0f, + gapPosition: GapPosition = GapPosition.Top +) = CircleProgress(listOf(percent), modifier, appearance, shape, gapDegree, gapPosition) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Line.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Line.kt new file mode 100644 index 000000000..522cf0287 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/Line.kt @@ -0,0 +1,71 @@ +package com.atls.hyperion.ui.components.progress + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import com.atls.hyperion.ui.components.progress.config.MAX_PERCENT +import com.atls.hyperion.ui.components.progress.config.MAX_WEIGHT +import com.atls.hyperion.ui.components.progress.config.MIN_WEIGHT +import com.atls.hyperion.ui.components.progress.lib.getBrush +import com.atls.hyperion.ui.components.progress.lib.getSolidColor +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default + +@Composable +fun LineProgress( + percents: List, + modifier: Modifier = Modifier, + appearance: ProgressAppearance, + shape: ProgressShape = ProgressShape.default() +) { + Row( + modifier = modifier + .fillMaxWidth() + .height(shape.trailWidth) + .clip(shape.shape) + .background(appearance.colors.trailColor) + ) { + var accumulated = MIN_WEIGHT + + percents.forEachIndexed { index, percent -> + if (percent <= MIN_WEIGHT) return@forEachIndexed + + val segmentWeight = (percent / MAX_PERCENT).coerceAtMost(MAX_WEIGHT - accumulated) + if (segmentWeight <= MIN_WEIGHT) return@forEachIndexed + + val brush = getBrush(appearance.colors, index) + val color = getSolidColor(appearance.colors, index) + + Box( + Modifier + .height(shape.strokeWidth) + .weight(segmentWeight) + .then( + brush?.let { Modifier.background(it) } + ?: Modifier.background(color) + ) + ) + + accumulated += segmentWeight + } + + if (accumulated < MAX_WEIGHT) { + Spacer(Modifier.weight(MAX_WEIGHT - accumulated)) + } + } +} + +@Composable +fun LineProgress( + percent: Float, + modifier: Modifier = Modifier, + appearance: ProgressAppearance, + shape: ProgressShape = ProgressShape.default() +) = LineProgress(listOf(percent), modifier, appearance, shape) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/config/Constants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/config/Constants.kt new file mode 100644 index 000000000..bc265c44d --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/config/Constants.kt @@ -0,0 +1,16 @@ +package com.atls.hyperion.ui.components.progress.config + +const val FULL_CIRCLE = 360f +const val DEFAULT_GAP_DEGREE = 0f +const val DEFAULT_CANVAS_SCALE = 10f + +const val GAP_TOP_OFFSET = -90f +const val GAP_BOTTOM_OFFSET = 90f +const val GAP_LEFT_OFFSET = 180f +const val GAP_RIGHT_OFFSET = 0f + +const val MIN_PERCENT = 0f +const val MAX_PERCENT = 100f + +const val MIN_WEIGHT = 0f +const val MAX_WEIGHT = 1f diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetBrush.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetBrush.kt new file mode 100644 index 000000000..7d67ece94 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetBrush.kt @@ -0,0 +1,19 @@ +package com.atls.hyperion.ui.components.progress.lib + +import androidx.compose.ui.graphics.Brush +import com.atls.hyperion.ui.components.progress.styles.appearance.Colors +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +fun getBrush(colors: Colors, index: Int): Brush? = when (colors) { + is Colors.Single.Gradient -> colors.strokeBrush + is Colors.Multiple.Gradient -> colors.strokeBrushes.getOrElse(index) { + Brush.linearGradient( + listOf( + ThemeColors.Palette.transparent, + ThemeColors.Palette.transparent + ) + ) + } + + else -> null +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetSolidColor.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetSolidColor.kt new file mode 100644 index 000000000..a0b724183 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/lib/GetSolidColor.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.progress.lib + +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.ui.components.progress.styles.appearance.Colors +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +fun getSolidColor(colors: Colors, index: Int): Color = when (colors) { + is Colors.Single.Solid -> colors.strokeColor + is Colors.Multiple.Solid -> colors.strokeColors.getOrElse(index) { ThemeColors.Palette.transparent } + else -> ThemeColors.Palette.transparent +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/model/GapPosition.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/model/GapPosition.kt new file mode 100644 index 000000000..4b737c916 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/model/GapPosition.kt @@ -0,0 +1,5 @@ +package com.atls.hyperion.ui.components.progress.model + +enum class GapPosition { + Top, Bottom, Left, Right +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Circle.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Circle.kt new file mode 100644 index 000000000..21f1d13fe --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Circle.kt @@ -0,0 +1,37 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.progress.CircleProgress +import com.atls.hyperion.ui.components.progress.model.GapPosition +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.appearance.primary +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default +import com.atls.hyperion.ui.components.progress.styles.shape.thick +import com.atls.hyperion.ui.primitives.layout.column.Column + +@Composable +fun CircleProgressVariants(percent: Float) { + ComponentVariants( + name = "Circle Progress", + appearances = listOf( + "Primary" to { ProgressAppearance.primary() }, + "Gradient" to { ProgressAppearance.gradientExample() } + ), + shapes = listOf( + "Default" to { ProgressShape.default() }, + "Thick" to { ProgressShape.thick() }) + ) { appearance, shape -> + Column(horizontalAlignment = Alignment.CenterHorizontally) { + CircleProgress( + percent = percent, + appearance = appearance, + shape = shape, + gapDegree = 60f, + gapPosition = GapPosition.Top + ) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Component.kt new file mode 100644 index 000000000..7f1d11c59 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Component.kt @@ -0,0 +1,45 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.primitives.VerticalSpacer +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class ProgressStory : ComponentExample { + override val name: String = "Progress" + + @Composable + override fun Content() { + var percent by remember { mutableStateOf(40f) } + + Column(modifier = Modifier.fillMaxSize()) { + PercentSlider(percent) { percent = it } + VerticalSpacer(Space.md) + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(horizontal = Space.lg) + ) { + LineProgressVariants(percent) + VerticalSpacer(Space.lg) + SegmentedLineProgressVariants(percent) + VerticalSpacer(Space.xl3) + CircleProgressVariants(percent) + VerticalSpacer(Space.lg) + SegmentedCircleProgressVariants(percent) + VerticalSpacer(Space.xl3) + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/GradientExample.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/GradientExample.kt new file mode 100644 index 000000000..82658143f --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/GradientExample.kt @@ -0,0 +1,15 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.ui.components.progress.styles.appearance.Colors +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +fun ProgressAppearance.Companion.gradientExample(): ProgressAppearance = + ProgressAppearance( + colors = Colors.Single.Gradient( + strokeBrush = Brush.horizontalGradient(colors = listOf(Color.Magenta, Color.Cyan)), + trailColor = ThemeColors.Palette.gray + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Line.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Line.kt new file mode 100644 index 000000000..8f37076db --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/Line.kt @@ -0,0 +1,34 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.progress.LineProgress +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.appearance.primary +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default +import com.atls.hyperion.ui.components.progress.styles.shape.thick + +@Composable +fun LineProgressVariants(percent: Float) { + ComponentVariants( + name = "Line Progress", + appearances = listOf( + "Primary" to { ProgressAppearance.primary() }, + "Gradient" to { ProgressAppearance.gradientExample() } + ), + shapes = listOf( + "Default" to { ProgressShape.default() }, + "Thick" to { ProgressShape.thick() } + ) + ) { appearance, shape -> + LineProgress( + percent = percent, + appearance = appearance, + shape = shape, + modifier = Modifier.fillMaxWidth() + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/PercentSlider.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/PercentSlider.kt new file mode 100644 index 000000000..a03a72e33 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/PercentSlider.kt @@ -0,0 +1,18 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Slider +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.ui.primitives.layout.column.Column +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@Composable +fun PercentSlider(percent: Float, onChange: (Float) -> Unit) { + Column(modifier = Modifier.fillMaxWidth().padding(Space.lg)) { + Text("Percent: ${percent.toInt()}%") + Slider(value = percent, onValueChange = onChange, valueRange = 0f..100f) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedCircle.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedCircle.kt new file mode 100644 index 000000000..5f83e09ac --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedCircle.kt @@ -0,0 +1,40 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.progress.CircleProgress +import com.atls.hyperion.ui.components.progress.styles.appearance.Colors +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.appearance.primary +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default +import com.atls.hyperion.ui.components.progress.styles.shape.thick +import com.atls.hyperion.ui.primitives.layout.column.Column +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +@Composable +fun SegmentedCircleProgressVariants(percent: Float) { + val segments = List(3) { percent / 3 } + val multiColors = Colors.Multiple.Solid( + strokeColors = listOf( + ThemeColors.Palette.red, + ThemeColors.Palette.blueProtective, + ThemeColors.Palette.green + ), + trailColor = ThemeColors.Palette.gray + ) + ComponentVariants( + name = "Segmented Circle Progress", + appearances = listOf("Multi-color" to { + ProgressAppearance.primary().copy(colors = multiColors) + }), + shapes = listOf( + "Default" to { ProgressShape.default() }, + "Thick" to { ProgressShape.thick() }) + ) { appearance, shape -> + Column(horizontalAlignment = Alignment.CenterHorizontally) { + CircleProgress(percents = segments, appearance = appearance, shape = shape) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedLine.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedLine.kt new file mode 100644 index 000000000..c93b68544 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/stories/SegmentedLine.kt @@ -0,0 +1,43 @@ +package com.atls.hyperion.ui.components.progress.stories + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.progress.LineProgress +import com.atls.hyperion.ui.components.progress.styles.appearance.Colors +import com.atls.hyperion.ui.components.progress.styles.appearance.ProgressAppearance +import com.atls.hyperion.ui.components.progress.styles.appearance.primary +import com.atls.hyperion.ui.components.progress.styles.shape.ProgressShape +import com.atls.hyperion.ui.components.progress.styles.shape.default +import com.atls.hyperion.ui.components.progress.styles.shape.thick +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +@Composable +fun SegmentedLineProgressVariants(percent: Float) { + val segments = List(3) { percent / 3 } + val multiColors = Colors.Multiple.Solid( + strokeColors = listOf( + ThemeColors.Palette.red, + ThemeColors.Palette.blueProtective, + ThemeColors.Palette.green + ), + trailColor = ThemeColors.Palette.gray + ) + ComponentVariants( + name = "Segmented Line Progress", + appearances = listOf("Multi-color" to { + ProgressAppearance.primary().copy(colors = multiColors) + }), + shapes = listOf( + "Default" to { ProgressShape.default() }, + "Thick" to { ProgressShape.thick() }) + ) { appearance, shape -> + LineProgress( + percents = segments, + appearance = appearance, + shape = shape, + modifier = Modifier.fillMaxWidth() + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Appearance.kt new file mode 100644 index 000000000..a0b20443e --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Appearance.kt @@ -0,0 +1,7 @@ +package com.atls.hyperion.ui.components.progress.styles.appearance + +data class ProgressAppearance( + val colors: Colors +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Colors.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Colors.kt new file mode 100644 index 000000000..9019e12be --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Colors.kt @@ -0,0 +1,32 @@ +package com.atls.hyperion.ui.components.progress.styles.appearance + +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color + +sealed class Colors { + abstract val trailColor: Color + + sealed class Single : Colors() { + data class Solid( + val strokeColor: Color, + override val trailColor: Color + ) : Single() + + data class Gradient( + val strokeBrush: Brush, + override val trailColor: Color + ) : Single() + } + + sealed class Multiple : Colors() { + data class Solid( + val strokeColors: List, + override val trailColor: Color + ) : Multiple() + + data class Gradient( + val strokeBrushes: List, + override val trailColor: Color + ) : Multiple() + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Variants.kt new file mode 100644 index 000000000..91c45b050 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/appearance/Variants.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.progress.styles.appearance + +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +fun ProgressAppearance.Companion.primary(): ProgressAppearance = + ProgressAppearance( + colors = Colors.Single.Solid( + strokeColor = ThemeColors.Palette.blueProtective, + trailColor = ThemeColors.Palette.gray + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Shape.kt new file mode 100644 index 000000000..05b5e8271 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Shape.kt @@ -0,0 +1,16 @@ +package com.atls.hyperion.ui.components.progress.styles.shape + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.unit.Dp + +data class ProgressShape( + val cornerRadius: Dp, + val strokeWidth: Dp, + val trailWidth: Dp = strokeWidth, + val strokeLinecap: StrokeCap = StrokeCap.Round, + val trailLinecap: StrokeCap = strokeLinecap, + val shape: RoundedCornerShape = RoundedCornerShape(cornerRadius) +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Variants.kt new file mode 100644 index 000000000..c6c3c94b3 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/progress/styles/shape/Variants.kt @@ -0,0 +1,18 @@ +package com.atls.hyperion.ui.components.progress.styles.shape + +import com.atls.hyperion.ui.theme.tokens.layout.BorderStroke +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius + +fun ProgressShape.Companion.default(): ProgressShape = + ProgressShape( + cornerRadius = CornerRadius.full, + strokeWidth = BorderStroke.medium, + trailWidth = BorderStroke.medium + ) + +fun ProgressShape.Companion.thick(): ProgressShape = + ProgressShape( + cornerRadius = CornerRadius.full, + strokeWidth = BorderStroke.huge, + trailWidth = BorderStroke.large + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/Switch.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/Component.kt similarity index 100% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/Switch.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/Component.kt diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/stories/Component.kt index 5015f5c81..5e83914cf 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/stories/Component.kt @@ -36,17 +36,17 @@ class SwitchStory : ComponentExample { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = Space.g12), + .padding(horizontal = Space.sm), verticalAlignment = Alignment.CenterVertically ) { Text(modifier = Modifier.weight(Weight.full), text = "Enabled") - HorizontalSpacer(Space.g12) + HorizontalSpacer(Space.sm) androidx.compose.material.Switch( checked = enabled, onCheckedChange = { enabled = it } ) } - VerticalSpacer(Space.g8) + VerticalSpacer(Space.xs2) ComponentVariants( name = "Switch", appearances = listOf( diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/styles/shape/Variants.kt index bda4ed823..cc9129e01 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/styles/shape/Variants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/switch/styles/shape/Variants.kt @@ -8,5 +8,5 @@ fun SwitchShape.Companion.medium(): SwitchShape = trackWidth = SwitchSize.defaultWidth, trackHeight = SwitchSize.defaultHeight, thumbSize = SwitchSize.defaultTrackSize, - thumbPadding = Space.g2 + thumbPadding = Space.xs5 ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/Toast.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/Toast.kt new file mode 100644 index 000000000..26dc90b78 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/Toast.kt @@ -0,0 +1,59 @@ +package com.atls.hyperion.ui.components.toast + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Snackbar +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import com.atls.hyperion.ui.components.toast.styles.appearance.ToastAppearance +import com.atls.hyperion.ui.components.toast.styles.appearance.default +import com.atls.hyperion.ui.components.toast.styles.shape.ToastShape +import com.atls.hyperion.ui.components.toast.styles.shape.default + +@Composable +fun Toast( + hostState: SnackbarHostState, + appearance: ToastAppearance = ToastAppearance.default(), + shape: ToastShape = ToastShape.default(), +) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.BottomCenter + ) { + SnackbarHost( + hostState = hostState + ) { data -> + Snackbar( + modifier = Modifier + .border( + BorderStroke(shape.borderStroke, appearance.borderColor), + RoundedCornerShape(shape.cornerRadius) + ), + shape = RoundedCornerShape(shape.cornerRadius), + containerColor = appearance.backgroundColor, + contentColor = appearance.textColor, + action = {} + ) { + Text( + text = data.visuals.message, + style = shape.typography, + textAlign = TextAlign.Center, + modifier = Modifier + .background(appearance.backgroundColor) + + .padding(shape.paddings) + ) + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/stories/Component.kt new file mode 100644 index 000000000..cef77fd51 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/stories/Component.kt @@ -0,0 +1,65 @@ +package com.atls.hyperion.ui.components.toast.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.toast.Toast +import com.atls.hyperion.ui.components.toast.styles.appearance.ToastAppearance +import com.atls.hyperion.ui.components.toast.styles.appearance.default +import com.atls.hyperion.ui.components.toast.styles.shape.ToastShape +import com.atls.hyperion.ui.components.toast.styles.shape.default +import com.atls.hyperion.ui.components.toast.styles.shape.rounded +import com.atls.hyperion.ui.components.toast.styles.shape.square +import kotlinx.coroutines.launch + +class ToastStories : ComponentExample { + override val name: String = "Toast" + + @Composable + override fun Content() { + val snackbarHostState = remember { SnackbarHostState() } + val scope = rememberCoroutineScope() + + var isVisible by remember { mutableStateOf(false) } + var toastText by remember { mutableStateOf("This is a toast message") } + + Column { + + ComponentVariants( + name = "Toast", + appearances = listOf( + "Default" to { ToastAppearance.default() } + ), + shapes = listOf( + "Default" to { ToastShape.default() }, + "Rounded" to { ToastShape.rounded() }, + "Square" to { ToastShape.square() } + ) + ) { appearance: ToastAppearance, shape: ToastShape -> + Button( + onClick = { + scope.launch { + snackbarHostState.showSnackbar("toast") + } + } + ) { + Text("Show Toast") + } + Toast( + hostState = snackbarHostState, + shape = shape, + appearance = appearance + ) + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Appearance.kt new file mode 100644 index 000000000..23029c4bf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Appearance.kt @@ -0,0 +1,12 @@ +package com.atls.hyperion.ui.components.toast.styles.appearance + +import androidx.compose.ui.graphics.Color +import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors + +data class ToastAppearance( + val backgroundColor: Color, + val textColor: Color, + val borderColor: Color = ThemeColors.Palette.transparent +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Variants.kt new file mode 100644 index 000000000..f7897599f --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/appearance/Variants.kt @@ -0,0 +1,10 @@ +package com.atls.hyperion.ui.components.toast.styles.appearance + +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +fun ToastAppearance.Companion.default(): ToastAppearance = + ToastAppearance( + backgroundColor = Colors.Palette.white, + textColor = Colors.Palette.black, + borderColor = Colors.Palette.gray + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Shape.kt new file mode 100644 index 000000000..1de1b0c07 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Shape.kt @@ -0,0 +1,16 @@ +package com.atls.hyperion.ui.components.toast.styles.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.Dp +import com.atls.hyperion.ui.theme.tokens.layout.Elevation + +data class ToastShape( + val cornerRadius: Dp, + val paddings: PaddingValues, + val typography: TextStyle, + val borderStroke: Dp, + val elevation: Dp = Elevation.zero +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Variants.kt new file mode 100644 index 000000000..514a8c6de --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/toast/styles/shape/Variants.kt @@ -0,0 +1,37 @@ +package com.atls.hyperion.ui.components.toast.styles.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import com.atls.hyperion.ui.theme.tokens.layout.BorderStroke +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.LineHeights + +@Composable +fun ToastShape.Companion.default(): ToastShape = + ToastShape( + cornerRadius = CornerRadius.xl2, + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.sm), + typography = TextStyle(fontSize = FontSize.md, lineHeight = LineHeights.md), + borderStroke = BorderStroke.tiny + ) + +@Composable +fun ToastShape.Companion.rounded(): ToastShape = + ToastShape( + cornerRadius = CornerRadius.xl4, + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.sm), + typography = TextStyle(fontSize = FontSize.md, lineHeight = LineHeights.md), + borderStroke = BorderStroke.tiny + ) + +@Composable +fun ToastShape.Companion.square(): ToastShape = + ToastShape( + cornerRadius = CornerRadius.zero, + paddings = PaddingValues(horizontal = Space.lg, vertical = Space.sm), + typography = TextStyle(fontSize = FontSize.md, lineHeight = LineHeights.md), + borderStroke = BorderStroke.tiny + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/Component.kt new file mode 100644 index 000000000..8b87d7fdf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/Component.kt @@ -0,0 +1,75 @@ +package com.atls.hyperion.ui.components.tooltip + +import androidx.compose.foundation.MutatePriority +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.RichTooltip +import androidx.compose.material3.TooltipAnchorPosition +import androidx.compose.material3.TooltipBox +import androidx.compose.material3.TooltipDefaults +import androidx.compose.material3.TooltipState +import androidx.compose.material3.rememberTooltipState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.PopupPositionProvider +import com.atls.hyperion.ui.components.tooltip.style.appearance.TooltipAppearance +import com.atls.hyperion.ui.components.tooltip.style.appearance.default +import com.atls.hyperion.ui.components.tooltip.style.shape.TooltipShape +import com.atls.hyperion.ui.components.tooltip.style.shape.default +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun Tooltip( + modifier: Modifier = Modifier, + appearance: TooltipAppearance = TooltipAppearance.default(), + shape: TooltipShape = TooltipShape.default(), + positionProvider: PopupPositionProvider = TooltipDefaults.rememberTooltipPositionProvider( + TooltipAnchorPosition.Below + ), + tooltipState: TooltipState = rememberTooltipState(), + tooltipContent: @Composable () -> Unit, + content: @Composable () -> Unit +) { + val scope = rememberCoroutineScope() + + TooltipBox( + positionProvider = positionProvider, + state = tooltipState, + onDismissRequest = { + tooltipState.dismiss() + }, + tooltip = { + RichTooltip( + shape = RoundedCornerShape(shape.cornerRadius), + colors = TooltipDefaults.richTooltipColors().copy( + containerColor = appearance.backgroundColor + ), + caretShape = TooltipDefaults.caretShape(shape.caretSize), + text = { + Box( + modifier = Modifier.padding(shape.padding) + ) { + tooltipContent() + } + } + ) + }, + content = { + Box( + modifier = modifier + .clickable { + scope.launch { + tooltipState.show(MutatePriority.PreventUserInput) + } + } + ) { + content() + } + } + ) +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Component.kt new file mode 100644 index 000000000..ef19f92ae --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Component.kt @@ -0,0 +1,28 @@ +package com.atls.hyperion.ui.components.tooltip.stories + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.ui.theme.tokens.layout.Space + +class TextTooltipStories : ComponentExample { + override val name: String = "Text Tooltip" + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + override fun Content() { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(Space.md), + verticalArrangement = Arrangement.spacedBy(Space.md) + ) { + TextTooltipVariants() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Text.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Text.kt new file mode 100644 index 000000000..1cc09b6f3 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/stories/Text.kt @@ -0,0 +1,50 @@ +package com.atls.hyperion.ui.components.tooltip.stories + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.tooltip.Tooltip +import com.atls.hyperion.ui.components.tooltip.style.appearance.TooltipAppearance +import com.atls.hyperion.ui.components.tooltip.style.appearance.default +import com.atls.hyperion.ui.components.tooltip.style.shape.TooltipShape +import com.atls.hyperion.ui.components.tooltip.style.shape.default +import com.atls.hyperion.ui.components.tooltip.ui.TextTooltipContent +import com.atls.hyperion.ui.theme.tokens.layout.Space + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TextTooltipVariants() { + ComponentVariants( + name = "Text Tooltip", + appearances = listOf( + "Default" to { TooltipAppearance.default() } + ), + shapes = listOf( + "Default" to { TooltipShape.default() } + ) + ) { appearance: TooltipAppearance, shape: TooltipShape -> + Tooltip( + appearance = appearance, + shape = shape, + tooltipContent = { + TextTooltipContent( + text = "This is a tooltip with ${shape::class.simpleName} shape", + onDismiss = {} + ) + } + ) { + Box( + modifier = Modifier + .padding(Space.md) + .fillMaxWidth() + ) { + Text("Click me") + } + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/Size.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/Size.kt new file mode 100644 index 000000000..7f9f63f57 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/Size.kt @@ -0,0 +1,8 @@ +package com.atls.hyperion.ui.components.tooltip.style + +import androidx.compose.ui.unit.dp + +object CaretSize { + val caretHeight = 8.dp + val caretWidth = 16.dp +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Appearance.kt new file mode 100644 index 000000000..7f7f22ff4 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Appearance.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.tooltip.style.appearance + +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color + +@Immutable +data class TooltipAppearance( + val backgroundColor: Color +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Variants.kt new file mode 100644 index 000000000..d07aef3d5 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/appearance/Variants.kt @@ -0,0 +1,10 @@ +package com.atls.hyperion.ui.components.tooltip.style.appearance + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +@Composable +fun TooltipAppearance.Companion.default() = + TooltipAppearance( + backgroundColor = Colors.Palette.white + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Shape.kt new file mode 100644 index 000000000..6a35654eb --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Shape.kt @@ -0,0 +1,15 @@ +package com.atls.hyperion.ui.components.tooltip.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Immutable +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpSize + +@Immutable +data class TooltipShape( + val cornerRadius: Dp, + val caretSize: DpSize, + val padding: PaddingValues +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Variants.kt new file mode 100644 index 000000000..8e98a92d2 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/style/shape/Variants.kt @@ -0,0 +1,19 @@ +package com.atls.hyperion.ui.components.tooltip.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.unit.DpSize +import com.atls.hyperion.ui.components.tooltip.style.CaretSize +import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius +import com.atls.hyperion.ui.theme.tokens.layout.Space + +fun TooltipShape.Companion.default() = + TooltipShape( + cornerRadius = CornerRadius.xl2, + caretSize = DpSize( + height = CaretSize.caretHeight, + width = CaretSize.caretWidth + ), + padding = PaddingValues( + vertical = Space.xs2 + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/ui/TextContent.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/ui/TextContent.kt new file mode 100644 index 000000000..398468a13 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/tooltip/ui/TextContent.kt @@ -0,0 +1,41 @@ +package com.atls.hyperion.ui.components.tooltip.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import com.atls.hyperion.ui.primitives.Text +import com.atls.hyperion.ui.theme.tokens.colors.Colors +import com.atls.hyperion.ui.theme.tokens.layout.Weight +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.FontWeight + +@Composable +fun TextTooltipContent( + modifier: Modifier = Modifier, + text: String, + color: Color = Colors.Palette.black, + typography: TextStyle = TextStyle( + fontSize = FontSize.xs2, + fontWeight = FontWeight.medium, + ), + onDismiss: () -> Unit +) { + Box( + modifier = modifier + .clickable(onClick = onDismiss) + .fillMaxWidth(Weight.large) + .verticalScroll(rememberScrollState()) + ) { + Text( + text = text, + color = color, + typography = typography + ) + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/Component.kt new file mode 100644 index 000000000..9519af6cf --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/Component.kt @@ -0,0 +1,97 @@ +package com.atls.hyperion.ui.components.topBar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.atls.hyperion.ui.components.topBar.style.appearance.TopBarAppearance +import com.atls.hyperion.ui.components.topBar.style.appearance.default +import com.atls.hyperion.ui.components.topBar.style.shape.TopBarShape +import com.atls.hyperion.ui.components.topBar.style.shape.default +import com.atls.hyperion.ui.primitives.Text +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.tokens.layout.Weight + +@Composable +fun TopBar( + modifier: Modifier = Modifier, + text: String, + appearance: TopBarAppearance = TopBarAppearance.default(), + shape: TopBarShape = TopBarShape.default(), + centerContent: (@Composable () -> Unit)? = null, + beforeContent: @Composable () -> Unit = {}, + afterContent: @Composable () -> Unit = {} +) { + val density = LocalDensity.current + var beforeWidthPx by remember { mutableStateOf(0) } + var afterWidthPx by remember { mutableStateOf(0) } + var rowHeightPx by remember { mutableStateOf(0) } + + BoxWithConstraints( + modifier = modifier + .fillMaxWidth() + .background(appearance.backgroundColor) + .padding(shape.paddings) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .onGloballyPositioned { rowHeightPx = it.size.height }, + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier.onGloballyPositioned { beforeWidthPx = it.size.width }, + contentAlignment = Alignment.CenterStart + ) { beforeContent() } + + Spacer(Modifier.weight(Weight.full)) + + Box( + modifier = Modifier.onGloballyPositioned { afterWidthPx = it.size.width }, + contentAlignment = Alignment.CenterEnd + ) { afterContent() } + } + + val horizontalPadding = + with(density) { maxOf(beforeWidthPx, afterWidthPx).toDp() } + Space.sm + val rowHeight = with(density) { rowHeightPx.toDp() } + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(start = horizontalPadding, end = horizontalPadding) + .then( + if (rowHeight > 0.dp) + Modifier.heightIn( + min = rowHeight + ) + else Modifier + ), + contentAlignment = Alignment.Center + ) { + if (centerContent == null) { + Text( + text = text, + textAlign = TextAlign.Center, + typography = shape.typography, + color = appearance.textColor + ) + } else centerContent() + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/stories/Component.kt new file mode 100644 index 000000000..7fb92fa5c --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/stories/Component.kt @@ -0,0 +1,55 @@ +package com.atls.hyperion.ui.components.topBar.stories + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.atls.hyperion.storybook.shared.model.ComponentExample +import com.atls.hyperion.storybook.shared.ui.ComponentVariants +import com.atls.hyperion.ui.components.topBar.TopBar +import com.atls.hyperion.ui.components.topBar.style.appearance.TopBarAppearance +import com.atls.hyperion.ui.components.topBar.style.appearance.default +import com.atls.hyperion.ui.components.topBar.style.shape.TopBarShape +import com.atls.hyperion.ui.components.topBar.style.shape.default + +class TopBarStory : ComponentExample { + override val name: String = "TopBar" + + @Composable + override fun Content() { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(bottom = 80.dp) + ) { + var text by remember { mutableStateOf("TopBar Title") } + + ComponentVariants( + name = "TopBar Variants", + appearances = listOf( + "Default" to { TopBarAppearance.default() } + ), + shapes = listOf( + "Default" to { TopBarShape.default() } + ) + ) { appearance, shape -> + TopBar( + text = text, + appearance = appearance, + shape = shape + ) + } + + Spacer(Modifier.height(24.dp)) + } + } +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Appearance.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Appearance.kt new file mode 100644 index 000000000..0b9959ff3 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Appearance.kt @@ -0,0 +1,10 @@ +package com.atls.hyperion.ui.components.topBar.style.appearance + +import androidx.compose.ui.graphics.Color + +data class TopBarAppearance( + val backgroundColor: Color, + val textColor: Color +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Variants.kt new file mode 100644 index 000000000..f24134a9e --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/appearance/Variants.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.topBar.style.appearance + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.theme.tokens.colors.Colors + +@Composable +fun TopBarAppearance.Companion.default(): TopBarAppearance = + TopBarAppearance( + backgroundColor = Colors.Palette.transparent, + textColor = Colors.Text.black + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Shape.kt new file mode 100644 index 000000000..e20d4da44 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Shape.kt @@ -0,0 +1,11 @@ +package com.atls.hyperion.ui.components.topBar.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.text.TextStyle + +data class TopBarShape( + val paddings: PaddingValues, + val typography: TextStyle +) { + companion object +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Variants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Variants.kt new file mode 100644 index 000000000..a09150791 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/components/topBar/style/shape/Variants.kt @@ -0,0 +1,23 @@ +package com.atls.hyperion.ui.components.topBar.style.shape + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import com.atls.hyperion.ui.theme.tokens.layout.Space +import com.atls.hyperion.ui.theme.typography.FontSize +import com.atls.hyperion.ui.theme.typography.FontWeight +import com.atls.hyperion.ui.theme.typography.NunitoSansFontFamily + +@Composable +fun TopBarShape.Companion.default(): TopBarShape = + TopBarShape( + paddings = PaddingValues( + horizontal = Space.xl3, + vertical = Space.zero + ), + typography = TextStyle( + fontWeight = FontWeight.bold, + fontSize = FontSize.xl4, + fontFamily = NunitoSansFontFamily() + ) + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DividerPosition.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DividerPosition.kt deleted file mode 100644 index a6340af9e..000000000 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DividerPosition.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.atls.hyperion.ui.fragment.datepicker.model - -enum class DividerPosition { - TOP, BOTTOM, NONE -} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Picker.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Picker.kt deleted file mode 100644 index 5746a0e12..000000000 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Picker.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape.variants - -import androidx.compose.runtime.Composable -import com.atls.hyperion.ui.fragment.datepicker.style.shape.CalendarShape -import com.atls.hyperion.ui.fragment.datepicker.style.shape.CellShape -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape -import com.atls.hyperion.ui.fragment.datepicker.style.shape.HeaderShape - -@Composable -fun DatePickerShape.Companion.default(): DatePickerShape = - DatePickerShape( - cellShape = CellShape.default(), - headerShape = HeaderShape.default(), - calendarShape = CalendarShape.default() - ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/Fragment.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/Fragment.kt similarity index 58% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/Fragment.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/Fragment.kt index 6fa36b2df..24078682a 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/Fragment.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/Fragment.kt @@ -1,14 +1,14 @@ -package com.atls.hyperion.ui.fragment.datepicker +package com.atls.hyperion.ui.fragments.datepicker import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.atls.hyperion.ui.components.modal.popup.Popup -import com.atls.hyperion.ui.fragment.datepicker.model.DateSelection -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.variants.default -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape -import com.atls.hyperion.ui.fragment.datepicker.style.shape.variants.default -import com.atls.hyperion.ui.fragment.datepicker.ui.DatePickerContent +import com.atls.hyperion.ui.fragments.datepicker.model.DateSelection +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.variants.default +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.variants.default +import com.atls.hyperion.ui.fragments.datepicker.ui.DatePickerContent @Composable fun DatePicker( diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/config/Constants.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/config/Constants.kt similarity index 52% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/config/Constants.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/config/Constants.kt index e86eadb6f..012acf8ad 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/config/Constants.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/config/Constants.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.config +package com.atls.hyperion.ui.fragments.datepicker.config internal val DAYS_IN_WEEK = 7 internal val WEEK_RANGE = 0..6 diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextDateRange.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextDateRange.kt similarity index 73% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextDateRange.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextDateRange.kt index cb65aa690..6eeaeced2 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextDateRange.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextDateRange.kt @@ -1,6 +1,6 @@ -package com.atls.hyperion.ui.fragment.datepicker.lib +package com.atls.hyperion.ui.fragments.datepicker.lib -import com.atls.hyperion.ui.fragment.datepicker.model.DateSelection +import com.atls.hyperion.ui.fragments.datepicker.model.DateSelection import kotlinx.datetime.LocalDate fun DateSelection.Range.next(clicked: LocalDate): DateSelection.Range = diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextMonth.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextMonth.kt similarity index 81% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextMonth.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextMonth.kt index 7d054307f..225cec205 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/NextMonth.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/NextMonth.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.lib +package com.atls.hyperion.ui.fragments.datepicker.lib import kotlinx.datetime.Month import kotlinx.datetime.YearMonth diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/PreviousMonth.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/PreviousMonth.kt similarity index 82% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/PreviousMonth.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/PreviousMonth.kt index 1610c86fb..e2445ec80 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/lib/PreviousMonth.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/lib/PreviousMonth.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.lib +package com.atls.hyperion.ui.fragments.datepicker.lib import kotlinx.datetime.Month import kotlinx.datetime.YearMonth diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DateSelection.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DateSelection.kt similarity index 82% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DateSelection.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DateSelection.kt index 2996cd71c..a03c94445 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/model/DateSelection.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DateSelection.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.model +package com.atls.hyperion.ui.fragments.datepicker.model import kotlinx.datetime.LocalDate diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DividerPosition.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DividerPosition.kt new file mode 100644 index 000000000..e2863e68f --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/model/DividerPosition.kt @@ -0,0 +1,5 @@ +package com.atls.hyperion.ui.fragments.datepicker.model + +enum class DividerPosition { + TOP, BOTTOM, NONE +} diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/stories/Component.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/stories/Component.kt similarity index 91% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/stories/Component.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/stories/Component.kt index 39b06502e..add56c035 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/stories/Component.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/stories/Component.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.stories +package com.atls.hyperion.ui.fragments.datepicker.stories import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding @@ -11,8 +11,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.atls.hyperion.storybook.shared.model.ComponentExample -import com.atls.hyperion.ui.fragment.datepicker.DatePicker -import com.atls.hyperion.ui.fragment.datepicker.model.DateSelection +import com.atls.hyperion.ui.fragments.datepicker.DatePicker +import com.atls.hyperion.ui.fragments.datepicker.model.DateSelection class DatePickerStory( override val name: String = "Date picker" diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Cell.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Cell.kt similarity index 87% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Cell.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Cell.kt index bca22879b..721dcbce6 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Cell.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Cell.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance +package com.atls.hyperion.ui.fragments.datepicker.style.appearance import androidx.compose.ui.graphics.Color diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Header.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Header.kt similarity index 69% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Header.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Header.kt index f1b5fc284..be2304d8d 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Header.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Header.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance +package com.atls.hyperion.ui.fragments.datepicker.style.appearance import androidx.compose.ui.graphics.Color diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Picker.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Picker.kt similarity index 89% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Picker.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Picker.kt index a6f0ee657..e3955ffe8 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/Picker.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/Picker.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance +package com.atls.hyperion.ui.fragments.datepicker.style.appearance import androidx.compose.ui.graphics.Color import com.atls.hyperion.ui.components.divider.style.appearance.DividerAppearance diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/WeekDays.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/WeekDays.kt similarity index 65% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/WeekDays.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/WeekDays.kt index 8f0b78e56..3febb7a1b 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/WeekDays.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/WeekDays.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance +package com.atls.hyperion.ui.fragments.datepicker.style.appearance import androidx.compose.ui.graphics.Color diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Cell.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Cell.kt similarity index 78% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Cell.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Cell.kt index 0119c7649..bbd05357b 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Cell.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Cell.kt @@ -1,7 +1,7 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance.variants +package com.atls.hyperion.ui.fragments.datepicker.style.appearance.variants import androidx.compose.runtime.Composable -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.CellAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.CellAppearance import com.atls.hyperion.ui.theme.tokens.colors.Colors as TokenColors @Composable diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Header.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Header.kt similarity index 65% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Header.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Header.kt index 28afb20bc..60f03b9eb 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Header.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Header.kt @@ -1,7 +1,7 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance.variants +package com.atls.hyperion.ui.fragments.datepicker.style.appearance.variants import androidx.compose.runtime.Composable -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.HeaderAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.HeaderAppearance import com.atls.hyperion.ui.theme.tokens.colors.Colors as TokenColors @Composable diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Picker.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Picker.kt similarity index 64% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Picker.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Picker.kt index 12282c766..d5094e52b 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/Picker.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/Picker.kt @@ -1,20 +1,20 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance.variants +package com.atls.hyperion.ui.fragments.datepicker.style.appearance.variants import androidx.compose.runtime.Composable import com.atls.hyperion.ui.components.divider.style.appearance.DividerAppearance import com.atls.hyperion.ui.components.divider.style.appearance.default import com.atls.hyperion.ui.components.modal.style.appearance.ModalAppearance import com.atls.hyperion.ui.components.modal.style.appearance.default -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.CellAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.HeaderAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.WeekDaysAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.CellAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.HeaderAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.WeekDaysAppearance import com.atls.hyperion.ui.theme.tokens.colors.Colors as TokenColors @Composable fun DatePickerAppearance.Companion.default(): DatePickerAppearance = DatePickerAppearance( - cellAppearance = CellAppearance.default(), + cellAppearance = CellAppearance.Companion.default(), headerAppearance = HeaderAppearance.default(), weekDaysAppearance = WeekDaysAppearance.default(), backgroundColor = TokenColors.Palette.white, diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/WeekDays.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/WeekDays.kt similarity index 62% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/WeekDays.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/WeekDays.kt index 61a3199c8..efda1b6c7 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/appearance/variants/WeekDays.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/appearance/variants/WeekDays.kt @@ -1,7 +1,7 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.appearance.variants +package com.atls.hyperion.ui.fragments.datepicker.style.appearance.variants import androidx.compose.runtime.Composable -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.WeekDaysAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.WeekDaysAppearance import com.atls.hyperion.ui.theme.tokens.colors.Colors as TokenColors @Composable diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Calendar.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Calendar.kt similarity index 75% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Calendar.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Calendar.kt index 5644885c7..4d71579c3 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Calendar.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Calendar.kt @@ -1,9 +1,9 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape +package com.atls.hyperion.ui.fragments.datepicker.style.shape import androidx.compose.foundation.layout.PaddingValues import com.atls.hyperion.ui.components.divider.style.shape.DividerShape import com.atls.hyperion.ui.components.modal.style.shape.ModalShape -import com.atls.hyperion.ui.fragment.datepicker.model.DividerPosition +import com.atls.hyperion.ui.fragments.datepicker.model.DividerPosition data class CalendarShape( val padding: PaddingValues, diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Cell.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Cell.kt similarity index 91% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Cell.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Cell.kt index 1ff8bd822..d84f68b22 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Cell.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Cell.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape +package com.atls.hyperion.ui.fragments.datepicker.style.shape import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Header.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Header.kt similarity index 79% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Header.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Header.kt index 8f3d4ad94..c5460a19c 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Header.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Header.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape +package com.atls.hyperion.ui.fragments.datepicker.style.shape import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Shape.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Shape.kt similarity index 72% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Shape.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Shape.kt index b552e3a92..0f0532cd9 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/Shape.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/Shape.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape +package com.atls.hyperion.ui.fragments.datepicker.style.shape data class DatePickerShape( val cellShape: CellShape, diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Calendar.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Calendar.kt similarity index 68% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Calendar.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Calendar.kt index 9c0f0fc14..bbd4bbdac 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Calendar.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Calendar.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape.variants +package com.atls.hyperion.ui.fragments.datepicker.style.shape.variants import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable @@ -6,14 +6,14 @@ import com.atls.hyperion.ui.components.divider.style.shape.DividerShape import com.atls.hyperion.ui.components.divider.style.shape.default import com.atls.hyperion.ui.components.modal.style.shape.ModalShape import com.atls.hyperion.ui.components.modal.style.shape.popup -import com.atls.hyperion.ui.fragment.datepicker.model.DividerPosition -import com.atls.hyperion.ui.fragment.datepicker.style.shape.CalendarShape +import com.atls.hyperion.ui.fragments.datepicker.model.DividerPosition +import com.atls.hyperion.ui.fragments.datepicker.style.shape.CalendarShape import com.atls.hyperion.ui.theme.tokens.layout.Space @Composable fun CalendarShape.Companion.default(): CalendarShape = CalendarShape( - padding = PaddingValues(Space.g12), + padding = PaddingValues(com.atls.hyperion.ui.theme.tokens.layout.Space.md), divider = DividerPosition.BOTTOM, dividerShape = DividerShape.default(), modalShape = ModalShape.popup() diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Cell.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Cell.kt similarity index 82% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Cell.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Cell.kt index 9488b92a8..fd5f0b5b1 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Cell.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Cell.kt @@ -1,9 +1,9 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape.variants +package com.atls.hyperion.ui.fragments.datepicker.style.shape.variants import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.text.TextStyle -import com.atls.hyperion.ui.fragment.datepicker.style.shape.CellShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.CellShape import com.atls.hyperion.ui.theme.tokens.layout.CornerRadius import com.atls.hyperion.ui.theme.tokens.layout.Space import com.atls.hyperion.ui.theme.typography.FontSize @@ -13,7 +13,7 @@ import com.atls.hyperion.ui.theme.typography.FontWeight fun CellShape.Companion.default(): CellShape = CellShape( spacing = Space.zero, - padding = Space.g8, + padding = Space.xs2, shape = RoundedCornerShape(CornerRadius.xs2), typography = TextStyle( fontSize = FontSize.xs, diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Header.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Header.kt similarity index 65% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Header.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Header.kt index f95c7a479..e84c3d0a3 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/style/shape/variants/Header.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Header.kt @@ -1,8 +1,8 @@ -package com.atls.hyperion.ui.fragment.datepicker.style.shape.variants +package com.atls.hyperion.ui.fragments.datepicker.style.shape.variants import androidx.compose.runtime.Composable import androidx.compose.ui.text.TextStyle -import com.atls.hyperion.ui.fragment.datepicker.style.shape.HeaderShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.HeaderShape import com.atls.hyperion.ui.primitives.icon.IconSize import com.atls.hyperion.ui.theme.tokens.layout.Space import com.atls.hyperion.ui.theme.typography.FontSize @@ -15,7 +15,7 @@ fun HeaderShape.Companion.default(): HeaderShape = fontSize = FontSize.md, fontWeight = FontWeight.bold, ), - spacing = Space.g12, + spacing = com.atls.hyperion.ui.theme.tokens.layout.Space.sm, iconSize = IconSize.medium, - horizontalPadding = Space.g12 + horizontalPadding = com.atls.hyperion.ui.theme.tokens.layout.Space.sm ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Picker.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Picker.kt new file mode 100644 index 000000000..90e4e8e38 --- /dev/null +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/style/shape/variants/Picker.kt @@ -0,0 +1,15 @@ +package com.atls.hyperion.ui.fragments.datepicker.style.shape.variants + +import androidx.compose.runtime.Composable +import com.atls.hyperion.ui.fragments.datepicker.style.shape.CalendarShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.CellShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.style.shape.HeaderShape + +@Composable +fun DatePickerShape.Companion.default(): DatePickerShape = + DatePickerShape( + cellShape = CellShape.default(), + headerShape = HeaderShape.Companion.default(), + calendarShape = CalendarShape.default() + ) diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/CalendarHeader.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/CalendarHeader.kt similarity index 90% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/CalendarHeader.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/CalendarHeader.kt index 1d82b3a63..74feaaae1 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/CalendarHeader.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/CalendarHeader.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.ui +package com.atls.hyperion.ui.fragments.datepicker.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -10,9 +10,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import com.atls.hyperion.ui.components.divider.horizontal.HorizontalDivider -import com.atls.hyperion.ui.fragment.datepicker.model.DividerPosition -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.model.DividerPosition +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape import com.atls.hyperion.ui.generated.resources.Res import com.atls.hyperion.ui.generated.resources.chevron_left import com.atls.hyperion.ui.generated.resources.chevron_right diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/DatePickerContent.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/DatePickerContent.kt similarity index 89% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/DatePickerContent.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/DatePickerContent.kt index 3e010b20c..10fab040a 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/DatePickerContent.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/DatePickerContent.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.ui +package com.atls.hyperion.ui.fragments.datepicker.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxWidth @@ -7,13 +7,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import com.atls.hyperion.ui.fragment.datepicker.config.DAYS_IN_WEEK -import com.atls.hyperion.ui.fragment.datepicker.config.WEEK_RANGE -import com.atls.hyperion.ui.fragment.datepicker.lib.next -import com.atls.hyperion.ui.fragment.datepicker.lib.previous -import com.atls.hyperion.ui.fragment.datepicker.model.DateSelection -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.config.DAYS_IN_WEEK +import com.atls.hyperion.ui.fragments.datepicker.config.WEEK_RANGE +import com.atls.hyperion.ui.fragments.datepicker.lib.next +import com.atls.hyperion.ui.fragments.datepicker.lib.previous +import com.atls.hyperion.ui.fragments.datepicker.model.DateSelection +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape import com.atls.hyperion.ui.primitives.layout.column.Column import com.kizitonwose.calendar.compose.HorizontalCalendar import com.kizitonwose.calendar.compose.rememberCalendarState diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/Day.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/Day.kt similarity index 93% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/Day.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/Day.kt index 72a8237cd..c25c3c7d0 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/Day.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/Day.kt @@ -1,4 +1,4 @@ -package com.atls.hyperion.ui.fragment.datepicker.ui +package com.atls.hyperion.ui.fragments.datepicker.ui import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -9,8 +9,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape import com.atls.hyperion.ui.primitives.Text import com.atls.hyperion.ui.shared.layout.aspectSquare import com.atls.hyperion.ui.theme.tokens.colors.Colors diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/WeekDays.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/WeekDays.kt similarity index 81% rename from mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/WeekDays.kt rename to mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/WeekDays.kt index d4a355a18..fb0a72e05 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragment/datepicker/ui/WeekDays.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/fragments/datepicker/ui/WeekDays.kt @@ -1,13 +1,13 @@ -package com.atls.hyperion.ui.fragment.datepicker.ui +package com.atls.hyperion.ui.fragments.datepicker.ui import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign -import com.atls.hyperion.ui.fragment.datepicker.config.DAYS_IN_WEEK -import com.atls.hyperion.ui.fragment.datepicker.style.appearance.DatePickerAppearance -import com.atls.hyperion.ui.fragment.datepicker.style.shape.DatePickerShape +import com.atls.hyperion.ui.fragments.datepicker.config.DAYS_IN_WEEK +import com.atls.hyperion.ui.fragments.datepicker.style.appearance.DatePickerAppearance +import com.atls.hyperion.ui.fragments.datepicker.style.shape.DatePickerShape import com.atls.hyperion.ui.primitives.Text import com.atls.hyperion.ui.theme.tokens.layout.Weight import kotlinx.datetime.DayOfWeek diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/icon/Size.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/icon/Size.kt index 8e6faec47..8b7316502 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/icon/Size.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/icon/Size.kt @@ -3,5 +3,6 @@ package com.atls.hyperion.ui.primitives.icon import androidx.compose.ui.unit.dp object IconSize { + val large = 32.dp val medium = 24.dp } diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Link.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Link.kt index 76a9a9bf0..3e42b59f4 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Link.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Link.kt @@ -19,7 +19,7 @@ class LinkStory : ComponentExample { @Composable override fun Content() { Column( - modifier = Modifier.padding(Space.g16) + modifier = Modifier.padding(Space.lg) ) { Link( textDecoration = "Standard Blue Link", @@ -30,7 +30,7 @@ class LinkStory : ComponentExample { lineHeight = LineHeights.md ) ) - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) Link( textDecoration = "Soft Blue Link", url = "https://google.com", @@ -40,7 +40,7 @@ class LinkStory : ComponentExample { lineHeight = LineHeights.md ) ) - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) Link( textDecoration = "Small Gray Link", url = "https://google.com", diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Text.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Text.kt index f3e878db8..a6735798f 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Text.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/primitives/stories/Text.kt @@ -19,7 +19,7 @@ class TextStory : ComponentExample { @Composable override fun Content() { Column( - modifier = Modifier.padding(Space.g16) + modifier = Modifier.padding(Space.lg) ) { Text( text = "Heading XL", @@ -29,7 +29,7 @@ class TextStory : ComponentExample { lineHeight = LineHeights.xl4 ) ) - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) Text( text = "Body Medium", color = Colors.Text.almostBlack, @@ -38,7 +38,7 @@ class TextStory : ComponentExample { lineHeight = LineHeights.md ) ) - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) Text( text = "Small Caption", color = Colors.Text.gray, @@ -47,7 +47,7 @@ class TextStory : ComponentExample { lineHeight = LineHeights.xs ) ) - VerticalSpacer(Space.g12) + VerticalSpacer(Space.sm) Text( text = "Error Text", color = Colors.Text.red, diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/effects/Alpha.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/effects/Alpha.kt index 6ef296fef..a8b5ca577 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/effects/Alpha.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/effects/Alpha.kt @@ -1,7 +1,9 @@ package com.atls.hyperion.ui.theme.tokens.effects object Alpha { + val full = 1f val huge = 0.9f val large = 0.8f val medium = 0.6f + val micro = 0.12f } diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Borders.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Borders.kt index ef8a9668a..c0d8d8ada 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Borders.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Borders.kt @@ -5,4 +5,7 @@ import androidx.compose.ui.unit.dp object BorderStroke { val none = 0.dp val tiny = 1.dp + val medium = 8.dp + val large = 12.dp + val huge = 16.dp } diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Elevation.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Elevation.kt index 29d13b027..f779aa15c 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Elevation.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Elevation.kt @@ -5,4 +5,5 @@ import androidx.compose.ui.unit.dp object Elevation { val zero = 0.dp val tiny = 2.dp + val medium = 8.dp } diff --git a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Spaces.kt b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Spaces.kt index 119557275..d67696155 100644 --- a/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Spaces.kt +++ b/mobile/kmp/ui/src/commonMain/kotlin/com/atls/hyperion/ui/theme/tokens/layout/Spaces.kt @@ -4,17 +4,15 @@ import androidx.compose.ui.unit.dp object Space { val zero = 0.dp - val g1 = 1.dp - val g2 = 2.dp - val g4 = 4.dp - val g6 = 6.dp - val g8 = 8.dp - val g10 = 10.dp - val g12 = 12.dp - val g14 = 14.dp - val g16 = 16.dp - val g17 = 17.dp - val g20 = 20.dp - val g22 = 22.dp - val g24 = 24.dp + val xs5 = 2.dp + val xs4 = 4.dp + val xs3 = 6.dp + val xs2 = 8.dp + val xs = 10.dp + val sm = 12.dp + val md = 14.dp + val lg = 16.dp + val xl = 20.dp + val xl2 = 22.dp + val xl3 = 24.dp }