diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index 2c6ea3d8..b268ef36 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -5,9 +5,6 @@ - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index e69de29b..7061a0d6 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,61 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml index 931b96c3..16660f1d 100644 --- a/.idea/runConfigurations.xml +++ b/.idea/runConfigurations.xml @@ -5,8 +5,12 @@ diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/ListPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/ListPreview.kt new file mode 100644 index 00000000..78bdcd99 --- /dev/null +++ b/app/src/main/kotlin/com/yourssu/handy/demo/ListPreview.kt @@ -0,0 +1,51 @@ +package com.yourssu.handy.demo + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.icons.HandyIcons +import com.yourssu.handy.compose.icons.line.ArrowsChevronRight +import com.yourssu.handy.compose.icons.line.User + +@Composable +@Preview +fun ListPreview() { + HandyTheme { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + com.yourssu.handy.compose.list.List( + headline = "Enable List Title", + onClick = {}, + leadingIcon = HandyIcons.Line.User, + trailingIcon = HandyIcons.Line.ArrowsChevronRight, + ) + + com.yourssu.handy.compose.list.List( + headline = "Disable List Title", + onClick = {}, + leadingIcon = HandyIcons.Line.User, + trailingIcon = HandyIcons.Line.ArrowsChevronRight, + enabled = false + ) + + com.yourssu.handy.compose.list.List( + headline = "Loooooooooong Titleeeeeeeeeeeeeeeeeeeeeeeeeee", + onClick = {}, + leadingIcon = HandyIcons.Line.User, + trailingIcon = HandyIcons.Line.ArrowsChevronRight, + ) + + com.yourssu.handy.compose.list.List( + headline = "Default Title", + onClick = {}, + ) + } + } +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt index 5a50a8de..981c275b 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt @@ -123,6 +123,11 @@ data class ColorScheme( val switchSelected: Color = ColorViolet500, val switchDisabled: Color = ColorGray200, val switchThumb: Color = ColorNeutralWhite, + + // List + val listEnabled: Color = ColorNeutralWhite, + val listPressed: Color = ColorGray50, + val listDisabled: Color = ColorNeutralWhite, ) val lightColorScheme = ColorScheme() diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/list/List.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/list/List.kt new file mode 100644 index 00000000..494b8176 --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/list/List.kt @@ -0,0 +1,112 @@ +package com.yourssu.handy.compose.list + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +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.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.Icon +import com.yourssu.handy.compose.Text +import com.yourssu.handy.compose.icons.HandyIcons +import com.yourssu.handy.compose.icons.line.ArrowsChevronRight +import com.yourssu.handy.compose.icons.line.User + +@Composable +fun List( + headline: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + leadingIcon: ImageVector? = null, + trailingIcon: ImageVector? = null, + headlineColor: Color = HandyTheme.colors.textBasicPrimary, + leadingIconColor: Color = HandyTheme.colors.iconBasicPrimary, + tailingIconColor: Color = HandyTheme.colors.iconBasicTertiary, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } +) { + val pressed by interactionSource.collectIsPressedAsState() + val backgroundColor = determineContainerColor(enabled, pressed) + + Row( + modifier = modifier + .fillMaxWidth() + .height(64.dp) + .clickable( + onClick = onClick, + enabled = enabled, + interactionSource = interactionSource, + indication = null + ) + .background(backgroundColor), + verticalAlignment = Alignment.CenterVertically, + ) { + leadingIcon?.let { + Icon( + imageVector = leadingIcon, + contentDescription = "leadingIcon", + tint = determineContentColor(enabled, leadingIconColor), + modifier = Modifier.padding(start = 16.dp) + ) + } + + Text( + text = headline, + color = determineContentColor(enabled, headlineColor), + modifier = Modifier + .padding(horizontal = 16.dp) + .weight(1f), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + + trailingIcon?.let { + Icon( + imageVector = trailingIcon, + contentDescription = "trailingIcon", + tint = determineContentColor(enabled, tailingIconColor), + modifier = Modifier + .padding(end = 16.dp) + .align(Alignment.CenterVertically) + ) + } + } +} + +@Composable +fun determineContainerColor( + enabled: Boolean, + pressed: Boolean, +): Color { + return when { + !enabled -> HandyTheme.colors.listDisabled + pressed -> HandyTheme.colors.listPressed + else -> HandyTheme.colors.listEnabled + } +} + +@Composable +fun determineContentColor( + enabled: Boolean, + contentColor: Color +): Color { + return when { + !enabled -> HandyTheme.colors.textBasicDisabled + else -> contentColor + } +} \ No newline at end of file