Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
438c709
feat(ui): input styles
comfrt1k Jan 12, 2026
0d651ef
feat(ui): input locals
comfrt1k Jan 12, 2026
25c5786
feat(ui): input component
comfrt1k Jan 12, 2026
4fa29c2
feat(theme): alpha tokens
comfrt1k Jan 12, 2026
2a026a3
feat(ui): switch styles
comfrt1k Jan 12, 2026
3888d58
feat(ui): switch component
comfrt1k Jan 12, 2026
44202f0
feat(ui): column layouts
comfrt1k Jan 12, 2026
c4b5734
feat(ui): grid layout
comfrt1k Jan 12, 2026
43b1966
feat(ui): row layout
comfrt1k Jan 12, 2026
e2a437e
feat(ui): date picker week days
comfrt1k Jan 13, 2026
f0c73fd
feat(ui): calendar header component
comfrt1k Jan 13, 2026
0bdfe49
feat(ui): date picker day component
comfrt1k Jan 13, 2026
202bf44
chore(theme): aspect square util
comfrt1k Jan 13, 2026
9987ce9
chore(theme): icon sizes
comfrt1k Jan 13, 2026
7e9c5ce
feat(ui): date picker components
comfrt1k Jan 13, 2026
12d5782
feat(ui): date picker fragment
comfrt1k Jan 13, 2026
be56069
feat(ui): date picker model
comfrt1k Jan 13, 2026
27c19d8
feat(ui): date utils
comfrt1k Jan 13, 2026
22f485a
chore(ui): date picker constants
comfrt1k Jan 13, 2026
b49d542
feat(ui): date picker styles
comfrt1k Jan 13, 2026
6b25b13
feat(ui): chevron icons
comfrt1k Jan 13, 2026
278ef5f
feat(theme): draghandle sizes
comfrt1k Jan 13, 2026
210881a
chore(theme): new elevation token
comfrt1k Jan 13, 2026
e681594
refactor(ui): rename divider files
comfrt1k Jan 13, 2026
55eae6d
feat(ui): drag handle component
comfrt1k Jan 13, 2026
a04a68b
feat(ui): modal styles
comfrt1k Jan 13, 2026
f813368
feat(ui): modal components with stories
comfrt1k Jan 13, 2026
90c4ea2
feat(ui): date picker stories
comfrt1k Jan 13, 2026
66b844c
feat(ui): date/calendar deps
comfrt1k Jan 13, 2026
6633cda
chore(storybook): spacing for component variants
comfrt1k Jan 13, 2026
5bbdcc5
chore(deps): toml update
comfrt1k Jan 13, 2026
3834a64
feat(app): new stories usage
comfrt1k Jan 13, 2026
bf306c3
Merge branch 'feat/components-part1' into feat/components-part2
comfrt1k Jan 13, 2026
fe5a744
chore(input): remove todo
comfrt1k Jan 13, 2026
ccfaeb8
Merge remote-tracking branch 'origin/feat/components-part2' into feat…
comfrt1k Jan 13, 2026
c56b203
Merge branch 'feat/components-part1' into feat/components-part2
comfrt1k Jan 13, 2026
3c881b1
refactor(ui): move alpha from colors to effects
comfrt1k Jan 13, 2026
beea202
refactor(theme): move component sizes to components
comfrt1k Jan 13, 2026
7150f6d
refactor(theme): move elevation tokens to layout
comfrt1k Jan 13, 2026
2c20615
refactor(picker): split styles
comfrt1k Jan 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions mobile/kmp/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
[versions]
calendar = "2.9.0"
kotlin = "2.2.0"
ktor = "3.3.1"
compose = "1.10.0-rc02"
composeShadow = "2.0.4"
coilCompose = "3.3.0"
kotlinxDatetime = "0.6.1"
agp = "8.9.0"
androidx-activityCompose = "1.9.3"

[libraries]
compose-calendar = { module = "com.kizitonwose.calendar:compose-multiplatform", version.ref = "calendar" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
compose-shadow = { module = "com.adamglin:compose-shadow", version.ref = "composeShadow" }
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilCompose" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import com.atls.hyperion.ui.components.card.stories.CardStory
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.modal.bottom.stories.BottomDialogStory
import com.atls.hyperion.ui.components.modal.popup.stories.PopupStory
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.primitives.stories.LinkStory
import com.atls.hyperion.ui.primitives.stories.TextStory

Expand All @@ -19,10 +23,14 @@ fun App() {
Storybook(
components = listOf(
AvatarStory(),
BottomDialogStory(),
ButtonStory(),
CheckboxStory(),
DatePickerStory(),
DateRangePickerStory(),
DividerStory(),
InputStory(),
PopupStory(),
SwitchStory(),
CardStory(),
TextStory(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package com.atls.hyperion.storybook.shared.ui
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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Divider
Expand Down Expand Up @@ -55,6 +57,7 @@ fun <A, S> ComponentVariants(
fontSize = FontSize.small,
modifier = Modifier.padding(top = Padding.tiny)
)
Spacer(Modifier.width(Padding.small))
content(appearanceProvider(), shapeProvider())
}
Divider()
Expand Down
3 changes: 3 additions & 0 deletions mobile/kmp/ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@ kotlin {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.compose.shadow)
implementation(libs.coil.compose)
implementation(libs.coil.network.ktor)
implementation(libs.compose.calendar)
api(libs.kotlinx.datetime)
}

androidMain {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M18.325,6.175C18.781,6.63 18.781,7.369 18.325,7.825L12.15,14L18.325,20.175C18.781,20.63 18.781,21.369 18.325,21.825C17.869,22.28 17.131,22.28 16.675,21.825L9.675,14.825C9.219,14.369 9.219,13.63 9.675,13.175L16.675,6.175C17.131,5.719 17.869,5.719 18.325,6.175Z"
android:fillColor="#18181B"
android:fillType="evenOdd"/>
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8.293,5.293C8.683,4.902 9.317,4.902 9.707,5.293L15.707,11.293C16.098,11.683 16.098,12.317 15.707,12.707L9.707,18.707C9.317,19.098 8.683,19.098 8.293,18.707C7.902,18.317 7.902,17.683 8.293,17.293L13.586,12L8.293,6.707C7.902,6.317 7.902,5.683 8.293,5.293Z"
android:fillColor="#18181B"
android:fillType="evenOdd"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.atls.hyperion.ui.components.button.styles.appearance.Colors
import com.atls.hyperion.ui.components.button.styles.shape.ButtonShape
import com.atls.hyperion.ui.shared.addon.AddonPosition
import com.atls.hyperion.ui.shared.addon.AddonSlotManager
import com.atls.hyperion.ui.theme.tokens.Elevation
import com.atls.hyperion.ui.theme.tokens.layout.Elevation
import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors

@OptIn(ExperimentalMaterialApi::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.atls.hyperion.ui.components.button.styles.appearance

import androidx.compose.ui.unit.Dp
import com.atls.hyperion.ui.components.button.state.ButtonState
import com.atls.hyperion.ui.theme.tokens.Elevation
import com.atls.hyperion.ui.theme.tokens.layout.Elevation

data class ButtonAppearance(
val default: Colors,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.atls.hyperion.ui.components.card.style.appearance

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import com.atls.hyperion.ui.theme.tokens.Elevation
import com.atls.hyperion.ui.theme.tokens.layout.Elevation
import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors

data class CardAppearance(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.atls.hyperion.ui.components.checkbox.locals.LocalState
import com.atls.hyperion.ui.components.checkbox.state.State
import com.atls.hyperion.ui.components.checkbox.styles.appearance.CheckboxAppearance
import com.atls.hyperion.ui.components.checkbox.styles.shape.CheckboxShape
import com.atls.hyperion.ui.primitives.Icon
import com.atls.hyperion.ui.primitives.icon.Icon
import com.atls.hyperion.ui.theme.tokens.layout.Weight

@Composable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.atls.hyperion.ui.components.input

import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import com.atls.hyperion.ui.components.input.container.InputContainer
import com.atls.hyperion.ui.components.input.state.InputState
import com.atls.hyperion.ui.components.input.style.appearance.InputAppearance
import com.atls.hyperion.ui.components.input.style.shape.InputShape
import com.atls.hyperion.ui.shared.addon.AddonSlotManager
import com.atls.hyperion.ui.theme.tokens.layout.Weight
import com.atls.hyperion.ui.theme.tokens.colors.Colors as ThemeColors

@Composable
fun Input(
modifier: Modifier = Modifier,
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
isError: Boolean = false,
enabled: Boolean = true,
readOnly: Boolean = false,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
appearance: InputAppearance,
shape: InputShape,
visualTransformation: VisualTransformation = VisualTransformation.None,
addons: AddonSlotManager = AddonSlotManager(),
placeholder: @Composable (() -> Unit)? = null,
) {
val isFocused = interactionSource.collectIsFocusedAsState().value
val isPressed = interactionSource.collectIsPressedAsState().value

val currentState = when {
!enabled -> InputState.Disabled
isError -> InputState.Error
isPressed -> InputState.Active
isFocused -> InputState.Focused
value.text.isNotEmpty() -> InputState.Filled
else -> InputState.Default
}

val colors = appearance.getColorsFromState(currentState)

InputContainer(
modifier = modifier,
appearance = appearance,
shape = shape,
state = currentState,
addons = addons
) {
BasicTextField(
value = value,
onValueChange = onValueChange,
enabled = enabled,
readOnly = readOnly,
interactionSource = interactionSource,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
cursorBrush = SolidColor(colors.cursorColor),
textStyle = shape.typography.copy(color = colors.textColor),
visualTransformation = visualTransformation,
decorationBox = { innerTextField ->
if (value.text.isEmpty() && placeholder != null) {
placeholder()
}
innerTextField()
},
modifier = Modifier
.background(ThemeColors.Palette.transparent)
.padding(shape.textPaddings)
.weight(Weight.full)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.atls.hyperion.ui.components.input.container

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.atls.hyperion.ui.components.input.locals.LocalAppearance
import com.atls.hyperion.ui.components.input.locals.LocalState
import com.atls.hyperion.ui.components.input.state.InputState
import com.atls.hyperion.ui.components.input.style.appearance.InputAppearance
import com.atls.hyperion.ui.components.input.style.appearance.blue
import com.atls.hyperion.ui.components.input.style.shape.InputShape
import com.atls.hyperion.ui.components.input.style.shape.normal
import com.atls.hyperion.ui.shared.addon.AddonPosition
import com.atls.hyperion.ui.shared.addon.AddonSlotManager

@Composable
fun InputContainer(
modifier: Modifier = Modifier,
appearance: InputAppearance = InputAppearance.blue(),
shape: InputShape = InputShape.normal(),
state: InputState? = null,
addons: AddonSlotManager = AddonSlotManager(),
content: @Composable RowScope.(interactionSource: MutableInteractionSource) -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused = interactionSource.collectIsFocusedAsState().value
val isPressed = interactionSource.collectIsPressedAsState().value

val resolvedState = state ?: when {
isPressed -> InputState.Active
isFocused -> InputState.Focused
else -> InputState.Default
}

val colors = appearance.getColorsFromState(resolvedState)

CompositionLocalProvider(
LocalState provides resolvedState,
LocalAppearance provides appearance
) {
Row(
modifier = modifier
.border(
width = shape.borderStroke,
color = colors.borderColor,
shape = RoundedCornerShape(shape.cornerRadius)
)
.background(colors.backgroundColor, RoundedCornerShape(shape.cornerRadius))
.padding(shape.paddings),
verticalAlignment = Alignment.CenterVertically
) {
addons.get(AddonPosition.Before).forEach {
it.Content()
it.Spacer()
}

content(interactionSource)

addons.get(AddonPosition.After).forEach {
it.Spacer()
it.Content()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.atls.hyperion.ui.components.input.locals

import androidx.compose.runtime.compositionLocalOf
import com.atls.hyperion.ui.components.input.style.appearance.InputAppearance

val LocalAppearance = compositionLocalOf<InputAppearance> {
error("InputAppearance not provided")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.atls.hyperion.ui.components.input.locals

import androidx.compose.runtime.compositionLocalOf
import com.atls.hyperion.ui.components.input.state.InputState

val LocalState = compositionLocalOf<InputState> {
error("InputState not provided")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.atls.hyperion.ui.components.input.placeholder

import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.atls.hyperion.ui.components.input.style.appearance.InputAppearance
import com.atls.hyperion.ui.components.input.style.appearance.blue
import com.atls.hyperion.ui.components.input.style.shape.InputShape
import com.atls.hyperion.ui.components.input.style.shape.normal

@Composable
fun InputPlaceholder(
modifier: Modifier = Modifier,
text: String,
appearance: InputAppearance = InputAppearance.blue(),
shape: InputShape = InputShape.normal()
) {
Text(
modifier = modifier,
text = text,
color = appearance.default.textColor,
style = shape.typography
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.atls.hyperion.ui.components.input.state

sealed interface InputState {
data object Default : InputState
data object Focused : InputState
data object Filled : InputState
data object Disabled : InputState
data object Error : InputState
data object Active : InputState
}
Loading