From 6d69eec8956c8b302880c045a375cddf771d4397 Mon Sep 17 00:00:00 2001 From: Sun Date: Tue, 31 Dec 2024 00:46:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Chip=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/demo/ChipPreview.kt | 149 ++++++++++++++++++ .../kotlin/com/yourssu/handy/compose/Chip.kt | 104 ++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 app/src/main/kotlin/com/yourssu/handy/demo/ChipPreview.kt create mode 100644 compose/src/main/kotlin/com/yourssu/handy/compose/Chip.kt diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/ChipPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/ChipPreview.kt new file mode 100644 index 0000000..82e92c1 --- /dev/null +++ b/app/src/main/kotlin/com/yourssu/handy/demo/ChipPreview.kt @@ -0,0 +1,149 @@ +package com.yourssu.handy.demo + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color.Companion.White +import androidx.compose.ui.layout.VerticalAlignmentLine +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.Chip +import com.yourssu.handy.compose.ChipSize +import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.icons.HandyIcons +import com.yourssu.handy.compose.icons.line.Cancel +import com.yourssu.handy.compose.icons.line.Close +import com.yourssu.handy.compose.icons.line.Crop +import com.yourssu.handy.compose.icons.line.InfoCircle + +@Preview +@Composable +fun ChipPreview() { + HandyTheme { + Column ( + modifier = Modifier + .background(White) + .padding(10.dp), + verticalArrangement = Arrangement.spacedBy(30.dp) + ) { + Row ( + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Column ( + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Chip( + onCheckedChange = {}, + text = "Label", + checked = false + ) + + Chip( + onCheckedChange = {}, + text = "Label", + checked = true + ) + + Chip( + onCheckedChange = {}, + text = "Label", + enabled = false + ) + } + + Column ( + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Chip( + onCheckedChange = {}, + text = "Label", + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + checked = false + ) + + Chip( + onCheckedChange = {}, + text = "Label", + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + checked = true + ) + + Chip( + onCheckedChange = {}, + text = "Label", + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + enabled = false + ) + } + } + + Row ( + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Column ( + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + checked = false + ) + + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + checked = true + ) + + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + enabled = false + ) + } + + Column ( + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + checked = false + ) + + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + checked = true + ) + + Chip( + onCheckedChange = {}, + text = "Label", + sizeType = ChipSize.Small, + leftIcon = HandyIcons.Line.InfoCircle, + rightIcon = HandyIcons.Line.Close, + enabled = false + ) + } + } + } + } +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/Chip.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/Chip.kt new file mode 100644 index 0000000..197f4eb --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/Chip.kt @@ -0,0 +1,104 @@ +package com.yourssu.handy.compose + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.foundation.HandyTextStyle +import com.yourssu.handy.compose.foundation.HandyTypography + +sealed class ChipSize( + val height: Dp, + val iconSize: IconSize = IconSize.XS, + val horizontalPadding: Dp = 12.dp, + val round: Dp = 40.dp +) { + data object Small : ChipSize(height = 24.dp) + data object Medium : ChipSize(height = 32.dp) +} + +/** + * 정보를 입력하거나 선택하여 컨텐츠를 필터링할 수 있는 [Chip]입니다. + * + * @param onCheckedChange Chip의 선택 상태가 변경될 때 호출되는 함수 + * @param text Chip 내부 텍스트 + * @param sizeType Chip 사이즈 설정 : Small, Medium(Default) + * @param leftIcon Chip 내부 텍스트의 왼쪽에 표시되는 아이콘 + * @param rightIcon Chip 내부 텍스트의 오른쪽에 표시되는 아이콘 + * @param checked Chip의 선택 여부 + * @param enabled Chip의 활성화 여부 + */ +@Composable +fun Chip( + onCheckedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, + text: String, + sizeType: ChipSize = ChipSize.Medium, + leftIcon: ImageVector? = null, + rightIcon: ImageVector? = null, + checked: Boolean = false, + enabled: Boolean = true, +) { + val iconSize = sizeType.iconSize + val height = sizeType.height + val horizontalPadding = sizeType.horizontalPadding + val round = sizeType.round + + val typo = when { + checked -> HandyTypography.B3Sb14 + else -> HandyTypography.B3Rg14 + } + + val backgroundColor = when { + checked -> HandyTheme.colors.chipSelected + !enabled -> HandyTheme.colors.chipDisabled + else -> HandyTheme.colors.chipUnselected + } + + val contentColor = when { + checked -> HandyTheme.colors.textBrandPrimary + !enabled -> HandyTheme.colors.textBasicDisabled + else -> HandyTheme.colors.textBasicSecondary + } + + Surface( + checked = checked, + onCheckedChange = onCheckedChange, + modifier = modifier.height(height), + enabled = enabled, + rounding = round, + backgroundColor = backgroundColor, + contentColor = contentColor + ) { + Row( + modifier = Modifier.padding(horizontal = horizontalPadding), + verticalAlignment = Alignment.CenterVertically + ) { + leftIcon?.let { + Icon( + imageVector = leftIcon, + iconSize = iconSize, + modifier = Modifier.padding(end = 4.dp) + ) + } + + Text( + text = text, + style = typo, + ) + + rightIcon?.let { + Icon( + imageVector = rightIcon, + iconSize = iconSize, + modifier = Modifier.padding(start = 4.dp) + ) + } + } + } +} \ No newline at end of file