From a047e641f66afe7b40e14d23c51fcd3b411c41d7 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 00:37:20 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `ic_script` 아이콘 애셋 추가 (`core_designsystem_ic_script.xml`) --- .../main/res/drawable/core_designsystem_ic_script.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_script.xml diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_script.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_script.xml new file mode 100644 index 00000000..7add81a2 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_script.xml @@ -0,0 +1,10 @@ + + + From db78c61af15a1cee56ff96519e874bb380d29bde Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 00:37:41 +0900 Subject: [PATCH 02/10] =?UTF-8?q?refactor:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=ED=85=8C=EB=A7=88=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=A0=95=EC=9D=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PrezelColorScheme 내의 배경색 관련 토큰 값을 디자인 가이드에 맞춰 조정했습니다. * `bgLarge` 색상을 `CoolGray50`에서 `CoolGray100`으로 변경 * `bgDisabled` 색상을 `CoolGray100`에서 `CoolGray50`으로 변경 --- .../team/prezel/core/designsystem/theme/PrezelColorScheme.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/theme/PrezelColorScheme.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/theme/PrezelColorScheme.kt index 49120df1..80dfc477 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/theme/PrezelColorScheme.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/theme/PrezelColorScheme.kt @@ -27,9 +27,9 @@ internal object PrezelColorScheme { interactiveRegular = ColorTokens.Blue500, bgRegular = ColorTokens.Common0, bgMedium = ColorTokens.CoolGray10, - bgLarge = ColorTokens.CoolGray50, + bgLarge = ColorTokens.CoolGray100, bgScrim = ColorTokens.Common1000.copy(alpha = 0.32f), - bgDisabled = ColorTokens.CoolGray100, + bgDisabled = ColorTokens.CoolGray50, textSmall = ColorTokens.CoolGray300, textRegular = ColorTokens.CoolGray500, textMedium = ColorTokens.CoolGray700, From f49501d016c2cf164fb8013f4968927fada03e70 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 00:47:15 +0900 Subject: [PATCH 03/10] =?UTF-8?q?refactor:=20PrezelChipStyle=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelChipStyle의 상태별 색상 매핑 수정 디자인 시스템 가이드에 맞춰 `PrezelChip`의 배경색과 아이콘 색상 결정 로직을 개선했습니다. * **배경색(`containerColor`)**: * `DISABLED` 상태의 배경색을 `bgLarge`에서 `bgDisabled`로 변경했습니다. * `FILLED` 타입의 기본 배경색을 `bgMedium`에서 `bgLarge`로 변경했습니다. * **아이콘 색상(`iconColor`)**: * `FILLED` 타입일 때 기본 아이콘 색상을 `iconMedium`으로, `OUTLINED` 타입일 때 `iconRegular`를 사용하도록 세분화했습니다. --- .../designsystem/component/chip/PrezelChipStyle.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt index 2629ca56..dd78e505 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt @@ -104,10 +104,10 @@ data class PrezelChipStyle( chipColors.containerColor != Color.Unspecified -> chipColors.containerColor feedback == PrezelChipFeedback.BAD -> colors.feedbackBadSmall interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveXSmall - interaction == PrezelChipInteraction.DISABLED -> colors.bgLarge + interaction == PrezelChipInteraction.DISABLED -> colors.bgDisabled else -> { when (type) { - PrezelChipType.FILLED -> colors.bgMedium + PrezelChipType.FILLED -> colors.bgLarge PrezelChipType.OUTLINED -> colors.bgRegular } } @@ -124,7 +124,12 @@ data class PrezelChipStyle( feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> colors.iconDisabled - else -> colors.iconRegular + else -> { + when (type) { + PrezelChipType.FILLED -> colors.iconMedium + PrezelChipType.OUTLINED -> colors.iconRegular + } + } } @Composable From 3eff82d7bc962d23b593573c3691f78a1a8da752 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 00:49:02 +0900 Subject: [PATCH 04/10] =?UTF-8?q?chore:=20detekt=20JVM=20=ED=83=80?= =?UTF-8?q?=EA=B2=9F=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `build.gradle.kts` 내 `Detekt` 태스크 설정에 `jvmTarget = "21"`을 명시적으로 추가했습니다. * `io.gitlab.arturbosch.detekt.Detekt` 임포트문을 추가하고 관련 코드를 정리했습니다. --- Prezel/build.gradle.kts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Prezel/build.gradle.kts b/Prezel/build.gradle.kts index 85a41491..80ba2255 100644 --- a/Prezel/build.gradle.kts +++ b/Prezel/build.gradle.kts @@ -1,3 +1,5 @@ +import io.gitlab.arturbosch.detekt.Detekt + plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false @@ -29,7 +31,9 @@ subprojects { parallel = true } - tasks.withType().configureEach { + tasks.withType().configureEach { + jvmTarget = "21" + reports { txt.required.set(true) html.required.set(false) From 95908cb5628bf0b7a6d41d71b7744083628cbc08 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 01:05:01 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor:=20PrezelChip=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=95=84=EC=9D=B4=EC=BD=98/=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=83=89=EC=83=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelChip 아이콘 및 텍스트 색상 관리 로직 분리 `PrezelChip`의 내부 색상을 결정하는 `PrezelChipColors` 구조를 개선하여 아이콘과 텍스트 색상을 개별적으로 설정할 수 있도록 변경했습니다. * `PrezelChipColors`에서 `contentColor`를 제거하고 `iconColor`와 `textColor`로 세분화 * `LocalPrezelChipTextColor`, `LocalPrezelChipIconColor` 등 전용 `CompositionLocal` 추가 * `PrezelChipStyle` 내에서 상호작용 및 피드백 상태에 따른 `iconColor()`와 `textColor()` 계산 로직 분리 구현 * `PrezelChip` 컴포저블에서 `Icon`의 `tint`와 `Text`의 `color`에 각각 분리된 색상을 적용하도록 수정 * 기존 프리뷰 코드의 커스텀 컬러 설정을 변경된 구조에 맞게 업데이트 (예: `feedbackWarningRegular`를 아이콘과 텍스트 모두에 적용) --- .../designsystem/component/chip/PrezelChip.kt | 14 ++++---- .../component/chip/PrezelChipStyle.kt | 35 ++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt index a0478518..5b5d36da 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -45,7 +44,8 @@ fun PrezelChip( ) { CompositionLocalProvider( LocalTextStyle provides style.textStyle(), - LocalContentColor provides style.contentColor(), + LocalPrezelChipIconColor provides style.iconColor(), + LocalPrezelChipTextColor provides style.textColor(), ) { Row( modifier = Modifier.padding(style.contentPadding(iconOnly = iconOnly)), @@ -60,7 +60,7 @@ fun PrezelChip( if (hasIcon) { Spacer(modifier = Modifier.width(style.iconTextSpacing())) } - Text(text = text) + Text(text = text, color = LocalPrezelChipTextColor.current) } } } @@ -97,6 +97,7 @@ private fun PrezelChipIcon( painter = painterResource(id = iconResId), contentDescription = null, modifier = modifier.size(style.iconSize()), + tint = LocalPrezelChipIconColor.current, ) } @@ -191,7 +192,8 @@ private fun PrezelChipCustomPreview() { ), customColors = PrezelChipColors( containerColor = PrezelTheme.colors.feedbackWarningSmall, - contentColor = PrezelTheme.colors.feedbackWarningRegular, + iconColor = PrezelTheme.colors.feedbackWarningRegular, + textColor = PrezelTheme.colors.feedbackWarningRegular, ), ) @@ -206,7 +208,7 @@ private fun PrezelChipCustomPreview() { ), customColors = PrezelChipColors( containerColor = PrezelTheme.colors.feedbackBadSmall, - contentColor = PrezelTheme.colors.feedbackBadRegular, + textColor = PrezelTheme.colors.feedbackBadRegular, ), ) @@ -221,7 +223,7 @@ private fun PrezelChipCustomPreview() { ), customColors = PrezelChipColors( containerColor = Color(0xFFDBFFF6), - contentColor = Color(0xFF00A37A), + textColor = Color(0xFF00A37A), ), ) } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt index dd78e505..2208b741 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt @@ -19,6 +19,14 @@ import com.team.prezel.core.designsystem.theme.PrezelTheme internal val LocalPrezelChipColors = staticCompositionLocalOf { PrezelChipColors() } +internal val LocalPrezelChipTextColor = staticCompositionLocalOf { + error("No PrezelChipTextColor provided") +} + +internal val LocalPrezelChipIconColor = staticCompositionLocalOf { + error("No PrezelChipIconColor provided") +} + enum class PrezelChipType { FILLED, OUTLINED, @@ -43,7 +51,8 @@ enum class PrezelChipSize { @Immutable data class PrezelChipColors( val containerColor: Color = Color.Unspecified, - val contentColor: Color = Color.Unspecified, + val iconColor: Color = Color.Unspecified, + val textColor: Color = Color.Unspecified, ) @Immutable @@ -70,7 +79,7 @@ data class PrezelChipStyle( val borderColor = when { - chipColors.contentColor != Color.Unspecified -> chipColors.contentColor + chipColors.iconColor != Color.Unspecified -> chipColors.iconColor feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> colors.borderRegular @@ -115,12 +124,12 @@ data class PrezelChipStyle( } @Composable - internal fun contentColor( + internal fun iconColor( colors: PrezelColors = PrezelTheme.colors, chipColors: PrezelChipColors = LocalPrezelChipColors.current, ): Color = when { - chipColors.contentColor != Color.Unspecified -> chipColors.contentColor + chipColors.iconColor != Color.Unspecified -> chipColors.iconColor feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> colors.iconDisabled @@ -132,6 +141,24 @@ data class PrezelChipStyle( } } + @Composable + internal fun textColor( + colors: PrezelColors = PrezelTheme.colors, + chipColors: PrezelChipColors = LocalPrezelChipColors.current, + ): Color = + when { + chipColors.textColor != Color.Unspecified -> chipColors.textColor + feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular + interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular + interaction == PrezelChipInteraction.DISABLED -> colors.textDisabled + else -> { + when (type) { + PrezelChipType.FILLED -> colors.textMedium + PrezelChipType.OUTLINED -> colors.textRegular + } + } + } + @Composable internal fun contentPadding( iconOnly: Boolean, From 86ecace400300ff92208c18177a160b0bbc5ac34 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 12:45:14 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20PrezelChip=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A7=81=20=EB=B0=8F=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelChip 스타일 계산 로직 분리 및 Defaults 도입 기존 `PrezelChipStyle` 클래스에 집중되어 있던 스타일 계산 로직을 `PrezelChipDefaults` 객체로 분리하여 컴포넌트 구조를 개선했습니다. * `PrezelChipStyle.kt` 삭제 및 관련 로직을 `PrezelChipDefaults.kt`로 이동 * `PrezelChipDefault` 데이터 클래스를 통해 계산된 스타일 값(`shape`, `border`, `color` 등)을 한 번에 전달하도록 변경 * `PrezelChipDefaults.getDefault()`를 통해 상태별(Type, Size, Interaction, Feedback) 스타일 값을 동적으로 계산 * feat: PrezelChip 모델 정의 및 주석 추가 칩의 상태와 속성을 정의하는 enum 클래스들을 별도 파일로 분리하고 각 항목에 대한 설명을 추가했습니다. * `PrezelChipModels.kt` 신규 생성 * `PrezelChipType`, `PrezelChipSize`, `PrezelChipInteraction`, `PrezelChipFeedback` 이동 및 KDoc 주석 추가 * refactor: PrezelChip 및 PrezelIconChip 파라미터 구조 변경 `style: PrezelChipStyle` 객체를 통째로 받던 방식에서 개별 상태 값(`type`, `size` 등)을 직접 받도록 변경하여 사용성을 높였습니다. * `PrezelChip`, `PrezelIconChip`의 파라미터를 `type`, `size`, `interaction`, `feedback`으로 명시화 * `PrezelChip` 내부에서 `PrezelChipDefaults.getDefault`를 호출하여 스타일 설정 적용 * `PrezelChipIcon` 컴포저블이 `PrezelChipDefault` 설정을 주입받아 렌더링하도록 수정 * refactor: PrezelChip 프리뷰 코드 구조 개선 및 분리 반복되는 프리뷰 로직을 별도의 파일로 추출하여 가독성을 높이고 유지보수를 용이하게 했습니다. * `PrezelChipPreview.kt` 생성 및 공통 프리뷰 콘텐츠 함수(`PrezelChipPreviewContent` 등) 정의 * `PrezelChip.kt` 및 `PrezelIconChip.kt` 내 프리뷰 코드를 신규 분리된 함수를 사용하도록 리팩터링 * 사용자 정의 색상 테스트를 위한 `PrezelChipCustomPreviewContent` 추가 --- .../designsystem/component/chip/PrezelChip.kt | 189 +++++--------- .../component/chip/PrezelChipDefaults.kt | 238 ++++++++++++++++++ .../component/chip/PrezelChipModels.kt | 62 +++++ .../component/chip/PrezelChipPreview.kt | 116 +++++++++ .../component/chip/PrezelChipStyle.kt | 200 --------------- .../component/chip/PrezelIconChip.kt | 89 +++---- 6 files changed, 513 insertions(+), 381 deletions(-) create mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt create mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt create mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt delete mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt index 5b5d36da..c3f02730 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt @@ -15,50 +15,54 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview -import com.team.prezel.core.designsystem.preview.PreviewRow -import com.team.prezel.core.designsystem.preview.PreviewSection -import com.team.prezel.core.designsystem.preview.PreviewValueRow -import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelChip( modifier: Modifier = Modifier, text: String? = null, @DrawableRes iconResId: Int? = null, - style: PrezelChipStyle = PrezelChipStyle(), + type: PrezelChipType = PrezelChipType.FILLED, + size: PrezelChipSize = PrezelChipSize.REGULAR, + interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, + feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, + config: PrezelChipDefault = PrezelChipDefaults.getDefault( + iconOnly = text == null && iconResId != null, + type = type, + size = size, + interaction = interaction, + feedback = feedback, + ), ) { val hasText = text != null val hasIcon = iconResId != null - val iconOnly = hasIcon && !hasText require(hasText || hasIcon) { "Chip은 text 또는 icon 중 하나는 반드시 필요합니다." } Surface( modifier = modifier, - shape = style.shape(), - color = style.containerColor(iconOnly = iconOnly), - border = style.borderStroke(), + shape = config.shape, + color = config.containerColor, + border = config.borderStroke, ) { CompositionLocalProvider( - LocalTextStyle provides style.textStyle(), - LocalPrezelChipIconColor provides style.iconColor(), - LocalPrezelChipTextColor provides style.textColor(), + LocalTextStyle provides config.textStyle, + LocalPrezelChipIconColor provides config.iconColor, + LocalPrezelChipTextColor provides config.textColor, ) { Row( - modifier = Modifier.padding(style.contentPadding(iconOnly = iconOnly)), + modifier = Modifier.padding(config.contentPadding), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { iconResId?.let { resId -> - PrezelChipIcon(iconResId = resId, style = style) + PrezelChipIcon(iconResId = resId, config = config) } if (hasText) { if (hasIcon) { - Spacer(modifier = Modifier.width(style.iconTextSpacing())) + Spacer(modifier = Modifier.width(config.iconTextSpacing)) } Text(text = text, color = LocalPrezelChipTextColor.current) } @@ -72,17 +76,34 @@ fun PrezelChip( modifier: Modifier = Modifier, text: String? = null, @DrawableRes iconResId: Int? = null, - style: PrezelChipStyle = PrezelChipStyle(), + type: PrezelChipType = PrezelChipType.FILLED, + size: PrezelChipSize = PrezelChipSize.REGULAR, + interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, + feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, + config: PrezelChipDefault? = null, customColors: PrezelChipColors = LocalPrezelChipColors.current, ) { CompositionLocalProvider( LocalPrezelChipColors provides customColors, ) { + val resolvedConfig = + config ?: PrezelChipDefaults.getDefault( + iconOnly = text == null && iconResId != null, + type = type, + size = size, + interaction = interaction, + feedback = feedback, + ) + PrezelChip( modifier = modifier, text = text, iconResId = iconResId, - style = style, + type = type, + size = size, + interaction = interaction, + feedback = feedback, + config = resolvedConfig, ) } } @@ -90,13 +111,13 @@ fun PrezelChip( @Composable private fun PrezelChipIcon( @DrawableRes iconResId: Int, - style: PrezelChipStyle, + config: PrezelChipDefault, modifier: Modifier = Modifier, ) { Icon( painter = painterResource(id = iconResId), contentDescription = null, - modifier = modifier.size(style.iconSize()), + modifier = modifier.size(config.iconSize), tint = LocalPrezelChipIconColor.current, ) } @@ -104,128 +125,44 @@ private fun PrezelChipIcon( @BasicPreview @Composable private fun PrezelChipSizePreview() { - PreviewSection( - title = "Chip / Size", - description = "Chip의 크기를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipSize.entries.forEach { size -> - PreviewValueRow( - name = type.name, - valueLabel = size.name, - ) { - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, size = size), - ) - } - } - } + PrezelChipSizePreviewContent { type, size -> + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + size = size, + ) } } @BasicPreview @Composable private fun PrezelChipInteractionPreview() { - PreviewSection( - title = "Chip / Interaction", - description = "Chip의 상호작용 상태를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipInteraction.entries.forEach { interaction -> - PreviewValueRow( - name = type.name, - valueLabel = interaction.name, - ) { - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, interaction = interaction), - ) - } - } - } + PrezelChipInteractionPreviewContent { type, interaction -> + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + interaction = interaction, + ) } } @BasicPreview @Composable private fun PrezelChipFeedbackPreview() { - PreviewSection( - title = "Chip / Feedback", - description = "Chip의 피드백 상태를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipFeedback.entries.forEach { feedback -> - PreviewValueRow( - name = type.name, - valueLabel = feedback.name, - ) { - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, feedback = feedback), - ) - } - } - } + PrezelChipFeedbackPreviewContent { type, feedback -> + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + feedback = feedback, + ) } } @BasicPreview @Composable private fun PrezelChipCustomPreview() { - PreviewSection( - title = "Chip / Custom", - description = "사용자 정의된 색 지정이 가능합니다.", - ) { - PreviewRow { - PrezelChip( - text = "느려요", - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle( - type = PrezelChipType.FILLED, - size = PrezelChipSize.REGULAR, - interaction = PrezelChipInteraction.DISABLED, - feedback = PrezelChipFeedback.BAD, - ), - customColors = PrezelChipColors( - containerColor = PrezelTheme.colors.feedbackWarningSmall, - iconColor = PrezelTheme.colors.feedbackWarningRegular, - textColor = PrezelTheme.colors.feedbackWarningRegular, - ), - ) - - PrezelChip( - text = "빨라요", - iconResId = null, - style = PrezelChipStyle( - type = PrezelChipType.OUTLINED, - size = PrezelChipSize.REGULAR, - interaction = PrezelChipInteraction.DEFAULT, - feedback = PrezelChipFeedback.DEFAULT, - ), - customColors = PrezelChipColors( - containerColor = PrezelTheme.colors.feedbackBadSmall, - textColor = PrezelTheme.colors.feedbackBadRegular, - ), - ) - - PrezelChip( - text = "적당해요", - iconResId = null, - style = PrezelChipStyle( - type = PrezelChipType.FILLED, - size = PrezelChipSize.SMALL, - interaction = PrezelChipInteraction.ACTIVE, - feedback = PrezelChipFeedback.DEFAULT, - ), - customColors = PrezelChipColors( - containerColor = Color(0xFFDBFFF6), - textColor = Color(0xFF00A37A), - ), - ) - } - } + PrezelChipCustomPreviewContent() } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt new file mode 100644 index 00000000..ede7179e --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt @@ -0,0 +1,238 @@ +package com.team.prezel.core.designsystem.component.chip + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.team.prezel.core.designsystem.theme.PrezelTheme + +internal val LocalPrezelChipColors = staticCompositionLocalOf { PrezelChipColors() } + +internal val LocalPrezelChipTextColor = staticCompositionLocalOf { + error("No PrezelChipTextColor provided") +} + +internal val LocalPrezelChipIconColor = staticCompositionLocalOf { + error("No PrezelChipIconColor provided") +} + +@Immutable +data class PrezelChipColors( + val containerColor: Color = Color.Unspecified, + val iconColor: Color = Color.Unspecified, + val textColor: Color = Color.Unspecified, +) + +@Immutable +data class PrezelChipDefault( + val shape: Shape, + val borderStroke: BorderStroke?, + val textStyle: TextStyle, + val containerColor: Color, + val iconColor: Color, + val textColor: Color, + val contentPadding: PaddingValues, + val iconTextSpacing: Dp, + val iconSize: Dp, +) + +object PrezelChipDefaults { + @Composable + fun getDefault( + iconOnly: Boolean, + type: PrezelChipType = PrezelChipType.FILLED, + size: PrezelChipSize = PrezelChipSize.REGULAR, + interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, + feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, + chipColors: PrezelChipColors = LocalPrezelChipColors.current, + shape: Shape = getShape(size = size), + borderStroke: BorderStroke? = getBorderStroke( + type = type, + interaction = interaction, + feedback = feedback, + chipColors = chipColors, + ), + textStyle: TextStyle = getTextStyle(size = size), + containerColor: Color = getContainerColor( + iconOnly = iconOnly, + type = type, + interaction = interaction, + feedback = feedback, + chipColors = chipColors, + ), + iconColor: Color = getIconColor( + type = type, + interaction = interaction, + feedback = feedback, + chipColors = chipColors, + ), + textColor: Color = getTextColor( + type = type, + interaction = interaction, + feedback = feedback, + chipColors = chipColors, + ), + contentPadding: PaddingValues = getContentPadding(size = size, iconOnly = iconOnly), + iconTextSpacing: Dp = getIconTextSpacing(size = size), + iconSize: Dp = getIconSize(size = size), + ) = PrezelChipDefault( + shape = shape, + borderStroke = borderStroke, + textStyle = textStyle, + containerColor = containerColor, + iconColor = iconColor, + textColor = textColor, + contentPadding = contentPadding, + iconTextSpacing = iconTextSpacing, + iconSize = iconSize, + ) + + @Composable + private fun getShape(size: PrezelChipSize): Shape = + when (size) { + PrezelChipSize.SMALL -> PrezelTheme.shapes.V4 + PrezelChipSize.REGULAR -> PrezelTheme.shapes.V8 + } + + @Composable + private fun getBorderStroke( + type: PrezelChipType, + interaction: PrezelChipInteraction, + feedback: PrezelChipFeedback, + chipColors: PrezelChipColors, + ): BorderStroke? { + if (type == PrezelChipType.FILLED) return null + + val borderColor = + when { + chipColors.iconColor != Color.Unspecified -> chipColors.iconColor + feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular + interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular + interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.borderRegular + else -> PrezelTheme.colors.borderMedium + } + + return BorderStroke( + width = PrezelTheme.stroke.V1, + color = borderColor, + ) + } + + @Composable + private fun getTextStyle(size: PrezelChipSize): TextStyle = + when (size) { + PrezelChipSize.SMALL -> PrezelTheme.typography.caption2Regular + PrezelChipSize.REGULAR -> PrezelTheme.typography.caption1Regular + } + + @Composable + private fun getContainerColor( + iconOnly: Boolean, + type: PrezelChipType, + interaction: PrezelChipInteraction, + feedback: PrezelChipFeedback, + chipColors: PrezelChipColors, + ): Color { + if (type == PrezelChipType.OUTLINED && iconOnly) { + return Color.Transparent + } + + return when { + chipColors.containerColor != Color.Unspecified -> chipColors.containerColor + feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadSmall + interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveXSmall + interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.bgDisabled + else -> { + when (type) { + PrezelChipType.FILLED -> PrezelTheme.colors.bgLarge + PrezelChipType.OUTLINED -> PrezelTheme.colors.bgRegular + } + } + } + } + + @Composable + private fun getIconColor( + type: PrezelChipType, + interaction: PrezelChipInteraction, + feedback: PrezelChipFeedback, + chipColors: PrezelChipColors, + ): Color = + when { + chipColors.iconColor != Color.Unspecified -> chipColors.iconColor + feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular + interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular + interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.iconDisabled + else -> { + when (type) { + PrezelChipType.FILLED -> PrezelTheme.colors.iconMedium + PrezelChipType.OUTLINED -> PrezelTheme.colors.iconRegular + } + } + } + + @Composable + private fun getTextColor( + type: PrezelChipType, + interaction: PrezelChipInteraction, + feedback: PrezelChipFeedback, + chipColors: PrezelChipColors, + ): Color = + when { + chipColors.textColor != Color.Unspecified -> chipColors.textColor + feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular + interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular + interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.textDisabled + else -> { + when (type) { + PrezelChipType.FILLED -> PrezelTheme.colors.textMedium + PrezelChipType.OUTLINED -> PrezelTheme.colors.textRegular + } + } + } + + @Composable + private fun getContentPadding( + size: PrezelChipSize, + iconOnly: Boolean, + ): PaddingValues { + if (iconOnly) { + val all = when (size) { + PrezelChipSize.SMALL -> PrezelTheme.spacing.V6 + PrezelChipSize.REGULAR -> PrezelTheme.spacing.V8 + } + return PaddingValues(all = all) + } + + val horizontal = when (size) { + PrezelChipSize.SMALL -> PrezelTheme.spacing.V6 + PrezelChipSize.REGULAR -> PrezelTheme.spacing.V8 + } + + val vertical = when (size) { + PrezelChipSize.SMALL -> PrezelTheme.spacing.V4 + PrezelChipSize.REGULAR -> PrezelTheme.spacing.V6 + } + + return PaddingValues(horizontal = horizontal, vertical = vertical) + } + + @Composable + private fun getIconTextSpacing(size: PrezelChipSize): Dp = + when (size) { + PrezelChipSize.REGULAR -> PrezelTheme.spacing.V4 + PrezelChipSize.SMALL -> PrezelTheme.spacing.V2 + } + + private fun getIconSize(size: PrezelChipSize): Dp = + when (size) { + PrezelChipSize.SMALL -> 14.dp + PrezelChipSize.REGULAR -> 16.dp + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt new file mode 100644 index 00000000..16ca4f1e --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt @@ -0,0 +1,62 @@ +package com.team.prezel.core.designsystem.component.chip + +import androidx.compose.runtime.Immutable + +/** + * 칩의 시각적 타입을 정의합니다. + * + * Chip의 배경, 테두리 표현 방식을 구분할 때 사용합니다. + */ +@Immutable +enum class PrezelChipType { + /** 배경이 채워진 칩입니다. */ + FILLED, + + /** 테두리가 있는 칩입니다. */ + OUTLINED, +} + +/** + * 칩의 크기를 정의합니다. + * + * 칩의 높이, 패딩, 아이콘 크기, 텍스트 스타일의 기준으로 사용합니다. + */ +@Immutable +enum class PrezelChipSize { + /** 작은 크기의 칩입니다. */ + SMALL, + + /** 기본 크기의 칩입니다. */ + REGULAR, +} + +/** + * 칩의 상호작용 상태를 정의합니다. + * + * 선택 여부나 비활성 상태에 따라 칩의 강조 수준을 표현할 때 사용합니다. + */ +@Immutable +enum class PrezelChipInteraction { + /** 기본 상태의 칩입니다. */ + DEFAULT, + + /** 활성화되어 강조된 상태의 칩입니다. */ + ACTIVE, + + /** 비활성화된 상태의 칩입니다. */ + DISABLED, +} + +/** + * 칩의 피드백 상태를 정의합니다. + * + * 일반 상태 외에 경고성 의미를 함께 전달해야 할 때 사용합니다. + */ +@Immutable +enum class PrezelChipFeedback { + /** 일반 상태의 칩입니다. */ + DEFAULT, + + /** 부정적 피드백을 표현하는 칩입니다. */ + BAD, +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt new file mode 100644 index 00000000..75ee4f99 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt @@ -0,0 +1,116 @@ +package com.team.prezel.core.designsystem.component.chip + +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import com.team.prezel.core.designsystem.icon.PrezelIcons +import com.team.prezel.core.designsystem.preview.PreviewRow +import com.team.prezel.core.designsystem.preview.PreviewSection +import com.team.prezel.core.designsystem.preview.PreviewValueRow +import com.team.prezel.core.designsystem.theme.PrezelTheme + +@Composable +private fun PrezelChipPreviewContent( + previewTitle: String, + previewDescription: String, + values: List, + valueLabel: (T) -> String = { it.toString() }, + content: @Composable (PrezelChipType, T) -> Unit, +) { + PreviewSection( + title = previewTitle, + description = previewDescription, + ) { + PrezelChipType.entries.forEach { type -> + values.forEach { value -> + PreviewValueRow( + name = type.name, + valueLabel = valueLabel(value), + ) { + content(type, value) + } + } + } + } +} + +@Composable +internal fun PrezelChipSizePreviewContent(content: @Composable (PrezelChipType, PrezelChipSize) -> Unit) { + PrezelChipPreviewContent( + previewTitle = "Chip / Size", + previewDescription = "Chip의 크기를 조절합니다.", + values = PrezelChipSize.entries, + valueLabel = { it.name }, + content = content, + ) +} + +@Composable +internal fun PrezelChipInteractionPreviewContent(content: @Composable (PrezelChipType, PrezelChipInteraction) -> Unit) { + PrezelChipPreviewContent( + previewTitle = "Chip / Interaction", + previewDescription = "Chip의 상호작용 상태를 조절합니다.", + values = PrezelChipInteraction.entries, + valueLabel = { it.name }, + content = content, + ) +} + +@Composable +internal fun PrezelChipFeedbackPreviewContent(content: @Composable (PrezelChipType, PrezelChipFeedback) -> Unit) { + PrezelChipPreviewContent( + previewTitle = "Chip / Feedback", + previewDescription = "Chip의 피드백 상태를 조절합니다.", + values = PrezelChipFeedback.entries, + valueLabel = { it.name }, + content = content, + ) +} + +@Composable +internal fun PrezelChipCustomPreviewContent() { + PreviewSection( + title = "Chip / Custom", + description = "사용자 정의된 색 지정이 가능합니다.", + ) { + PreviewRow { + PrezelChip( + text = "느려요", + iconResId = PrezelIcons.Blank, + type = PrezelChipType.FILLED, + size = PrezelChipSize.REGULAR, + interaction = PrezelChipInteraction.DISABLED, + feedback = PrezelChipFeedback.BAD, + customColors = PrezelChipColors( + containerColor = PrezelTheme.colors.feedbackWarningSmall, + iconColor = PrezelTheme.colors.feedbackWarningRegular, + textColor = PrezelTheme.colors.feedbackWarningRegular, + ), + ) + + PrezelChip( + text = "빨라요", + type = PrezelChipType.OUTLINED, + size = PrezelChipSize.REGULAR, + interaction = PrezelChipInteraction.DEFAULT, + feedback = PrezelChipFeedback.DEFAULT, + customColors = PrezelChipColors( + containerColor = PrezelTheme.colors.feedbackBadSmall, + iconColor = PrezelTheme.colors.feedbackBadRegular, + textColor = PrezelTheme.colors.feedbackBadRegular, + ), + ) + + PrezelChip( + text = "적당해요", + type = PrezelChipType.FILLED, + size = PrezelChipSize.SMALL, + interaction = PrezelChipInteraction.ACTIVE, + feedback = PrezelChipFeedback.DEFAULT, + customColors = PrezelChipColors( + containerColor = Color(0xFFDBFFF6), + textColor = Color(0xFF00A37A), + ), + ) + } + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt deleted file mode 100644 index 2208b741..00000000 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipStyle.kt +++ /dev/null @@ -1,200 +0,0 @@ -package com.team.prezel.core.designsystem.component.chip - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.team.prezel.core.designsystem.foundation.color.PrezelColors -import com.team.prezel.core.designsystem.foundation.number.PrezelShapes -import com.team.prezel.core.designsystem.foundation.number.PrezelSpacing -import com.team.prezel.core.designsystem.foundation.number.PrezelStroke -import com.team.prezel.core.designsystem.foundation.typography.PrezelTypography -import com.team.prezel.core.designsystem.theme.PrezelTheme - -internal val LocalPrezelChipColors = staticCompositionLocalOf { PrezelChipColors() } - -internal val LocalPrezelChipTextColor = staticCompositionLocalOf { - error("No PrezelChipTextColor provided") -} - -internal val LocalPrezelChipIconColor = staticCompositionLocalOf { - error("No PrezelChipIconColor provided") -} - -enum class PrezelChipType { - FILLED, - OUTLINED, -} - -enum class PrezelChipInteraction { - DEFAULT, - ACTIVE, - DISABLED, -} - -enum class PrezelChipFeedback { - DEFAULT, - BAD, -} - -enum class PrezelChipSize { - SMALL, - REGULAR, -} - -@Immutable -data class PrezelChipColors( - val containerColor: Color = Color.Unspecified, - val iconColor: Color = Color.Unspecified, - val textColor: Color = Color.Unspecified, -) - -@Immutable -data class PrezelChipStyle( - val type: PrezelChipType = PrezelChipType.FILLED, - val size: PrezelChipSize = PrezelChipSize.REGULAR, - val interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, - val feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, -) { - @Composable - internal fun shape(shapes: PrezelShapes = PrezelTheme.shapes): Shape = - when (size) { - PrezelChipSize.SMALL -> shapes.V4 - PrezelChipSize.REGULAR -> shapes.V8 - } - - @Composable - internal fun borderStroke( - colors: PrezelColors = PrezelTheme.colors, - stroke: PrezelStroke = PrezelTheme.stroke, - chipColors: PrezelChipColors = LocalPrezelChipColors.current, - ): BorderStroke? { - if (type == PrezelChipType.FILLED) return null - - val borderColor = - when { - chipColors.iconColor != Color.Unspecified -> chipColors.iconColor - feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular - interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular - interaction == PrezelChipInteraction.DISABLED -> colors.borderRegular - else -> colors.borderMedium - } - - return BorderStroke( - width = stroke.V1, - color = borderColor, - ) - } - - @Composable - internal fun textStyle(typography: PrezelTypography = PrezelTheme.typography): TextStyle = - when (size) { - PrezelChipSize.SMALL -> typography.caption2Regular - PrezelChipSize.REGULAR -> typography.caption1Regular - } - - @Composable - internal fun containerColor( - iconOnly: Boolean, - colors: PrezelColors = PrezelTheme.colors, - chipColors: PrezelChipColors = LocalPrezelChipColors.current, - ): Color { - if (type == PrezelChipType.OUTLINED && iconOnly) { - return Color.Transparent - } - - return when { - chipColors.containerColor != Color.Unspecified -> chipColors.containerColor - feedback == PrezelChipFeedback.BAD -> colors.feedbackBadSmall - interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveXSmall - interaction == PrezelChipInteraction.DISABLED -> colors.bgDisabled - else -> { - when (type) { - PrezelChipType.FILLED -> colors.bgLarge - PrezelChipType.OUTLINED -> colors.bgRegular - } - } - } - } - - @Composable - internal fun iconColor( - colors: PrezelColors = PrezelTheme.colors, - chipColors: PrezelChipColors = LocalPrezelChipColors.current, - ): Color = - when { - chipColors.iconColor != Color.Unspecified -> chipColors.iconColor - feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular - interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular - interaction == PrezelChipInteraction.DISABLED -> colors.iconDisabled - else -> { - when (type) { - PrezelChipType.FILLED -> colors.iconMedium - PrezelChipType.OUTLINED -> colors.iconRegular - } - } - } - - @Composable - internal fun textColor( - colors: PrezelColors = PrezelTheme.colors, - chipColors: PrezelChipColors = LocalPrezelChipColors.current, - ): Color = - when { - chipColors.textColor != Color.Unspecified -> chipColors.textColor - feedback == PrezelChipFeedback.BAD -> colors.feedbackBadRegular - interaction == PrezelChipInteraction.ACTIVE -> colors.interactiveRegular - interaction == PrezelChipInteraction.DISABLED -> colors.textDisabled - else -> { - when (type) { - PrezelChipType.FILLED -> colors.textMedium - PrezelChipType.OUTLINED -> colors.textRegular - } - } - } - - @Composable - internal fun contentPadding( - iconOnly: Boolean, - spacing: PrezelSpacing = PrezelTheme.spacing, - ): PaddingValues { - if (iconOnly) { - val all = when (size) { - PrezelChipSize.SMALL -> spacing.V6 - PrezelChipSize.REGULAR -> spacing.V8 - } - return PaddingValues(all = all) - } - - val horizontal = when (size) { - PrezelChipSize.SMALL -> spacing.V6 - PrezelChipSize.REGULAR -> spacing.V8 - } - - val vertical = when (size) { - PrezelChipSize.SMALL -> spacing.V4 - PrezelChipSize.REGULAR -> spacing.V6 - } - - return PaddingValues(horizontal = horizontal, vertical = vertical) - } - - @Composable - internal fun iconTextSpacing(spacing: PrezelSpacing = PrezelTheme.spacing): Dp = - when (size) { - PrezelChipSize.REGULAR -> spacing.V4 - PrezelChipSize.SMALL -> spacing.V2 - } - - internal fun iconSize(): Dp = - when (size) { - PrezelChipSize.SMALL -> 14.dp - PrezelChipSize.REGULAR -> 16.dp - } -} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt index 3e7e6e17..33d11a15 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt @@ -5,87 +5,66 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview -import com.team.prezel.core.designsystem.preview.PreviewSection -import com.team.prezel.core.designsystem.preview.PreviewValueRow @Composable fun PrezelIconChip( @DrawableRes iconResId: Int, modifier: Modifier = Modifier, - style: PrezelChipStyle = PrezelChipStyle(), + type: PrezelChipType = PrezelChipType.FILLED, + size: PrezelChipSize = PrezelChipSize.REGULAR, + interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, + feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, + config: PrezelChipDefault = PrezelChipDefaults.getDefault( + iconOnly = true, + type = type, + size = size, + interaction = interaction, + feedback = feedback, + ), ) { PrezelChip( modifier = modifier, iconResId = iconResId, - style = style, + type = type, + size = size, + interaction = interaction, + feedback = feedback, + config = config, ) } @BasicPreview @Composable private fun PrezelChipSizePreview() { - PreviewSection( - title = "Chip / Size", - description = "Chip의 크기를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipSize.entries.forEach { size -> - PreviewValueRow( - name = type.name, - valueLabel = size.name, - ) { - PrezelIconChip( - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, size = size), - ) - } - } - } + PrezelChipSizePreviewContent { type, size -> + PrezelIconChip( + iconResId = PrezelIcons.Blank, + type = type, + size = size, + ) } } @BasicPreview @Composable private fun PrezelChipInteractionPreview() { - PreviewSection( - title = "Chip / Interaction", - description = "Chip의 상호작용 상태를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipInteraction.entries.forEach { interaction -> - PreviewValueRow( - name = type.name, - valueLabel = interaction.name, - ) { - PrezelIconChip( - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, interaction = interaction), - ) - } - } - } + PrezelChipInteractionPreviewContent { type, interaction -> + PrezelIconChip( + iconResId = PrezelIcons.Blank, + type = type, + interaction = interaction, + ) } } @BasicPreview @Composable private fun PrezelChipFeedbackPreview() { - PreviewSection( - title = "Chip / Feedback", - description = "Chip의 피드백 상태를 조절합니다.", - ) { - PrezelChipType.entries.forEach { type -> - PrezelChipFeedback.entries.forEach { feedback -> - PreviewValueRow( - name = type.name, - valueLabel = feedback.name, - ) { - PrezelIconChip( - iconResId = PrezelIcons.Blank, - style = PrezelChipStyle(type = type, feedback = feedback), - ) - } - } - } + PrezelChipFeedbackPreviewContent { type, feedback -> + PrezelIconChip( + iconResId = PrezelIcons.Blank, + type = type, + feedback = feedback, + ) } } From e3631684e84b4dbb944e4c68a6332f6190e37a66 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 7 Apr 2026 17:17:19 +0900 Subject: [PATCH 07/10] =?UTF-8?q?refactor:=20PrezelChip=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=84=A4=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelIconChip의 config 파라미터 초기화 로직 수정 `PrezelIconChip` 컴포저블의 `config` 파라미터 기본값을 `null`로 변경하고, 내부에서 `resolvedConfig`를 통해 초기화하도록 수정했습니다. 이는 파라미터로 전달된 값이 없을 때만 `PrezelChipDefaults.getDefault`가 호출되도록 보장합니다. * feat: PrezelChipColors 내 borderColor 필드 추가 및 적용 `PrezelChipColors` 데이터 클래스에 `borderColor` 필드를 추가하여 테두리 색상을 개별적으로 지정할 수 있도록 개선했습니다. * `PrezelChipColors`: `borderColor` 프로퍼티 추가 * `PrezelChipDefaults`: `borderColor`가 명시적으로 지정된 경우 이를 우선적으로 사용하도록 로직 수정 (기존에는 `iconColor`를 참조함) * `PrezelChipPreview`: 커스텀 컬러 테스트 케이스에 `borderColor` 설정 추가 --- .../designsystem/component/chip/PrezelChipDefaults.kt | 3 ++- .../designsystem/component/chip/PrezelChipPreview.kt | 1 + .../core/designsystem/component/chip/PrezelIconChip.kt | 10 ++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt index ede7179e..5e81c44c 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt @@ -25,6 +25,7 @@ internal val LocalPrezelChipIconColor = staticCompositionLocalOf { @Immutable data class PrezelChipColors( val containerColor: Color = Color.Unspecified, + val borderColor: Color = Color.Unspecified, val iconColor: Color = Color.Unspecified, val textColor: Color = Color.Unspecified, ) @@ -111,7 +112,7 @@ object PrezelChipDefaults { val borderColor = when { - chipColors.iconColor != Color.Unspecified -> chipColors.iconColor + chipColors.borderColor != Color.Unspecified -> chipColors.borderColor feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.borderRegular diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt index 75ee4f99..22577372 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt @@ -95,6 +95,7 @@ internal fun PrezelChipCustomPreviewContent() { feedback = PrezelChipFeedback.DEFAULT, customColors = PrezelChipColors( containerColor = PrezelTheme.colors.feedbackBadSmall, + borderColor = PrezelTheme.colors.feedbackBadRegular, iconColor = PrezelTheme.colors.feedbackBadRegular, textColor = PrezelTheme.colors.feedbackBadRegular, ), diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt index 33d11a15..6bf415d2 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt @@ -14,14 +14,16 @@ fun PrezelIconChip( size: PrezelChipSize = PrezelChipSize.REGULAR, interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, - config: PrezelChipDefault = PrezelChipDefaults.getDefault( + config: PrezelChipDefault? = null, +) { + val resolvedConfig = config ?: PrezelChipDefaults.getDefault( iconOnly = true, type = type, size = size, interaction = interaction, feedback = feedback, - ), -) { + ) + PrezelChip( modifier = modifier, iconResId = iconResId, @@ -29,7 +31,7 @@ fun PrezelIconChip( size = size, interaction = interaction, feedback = feedback, - config = config, + config = resolvedConfig, ) } From 0b3a673c00092db447e29e30e69f929c15147bbe Mon Sep 17 00:00:00 2001 From: moondev03 Date: Wed, 8 Apr 2026 21:08:54 +0900 Subject: [PATCH 08/10] =?UTF-8?q?refactor:=20PrezelChip=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20=EB=B0=8F=20=EB=82=B4=EB=B6=80=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelChip`의 가독성과 유지보수성을 높이기 위해 내부 상태 관리 방식을 변경하고 관련 파일을 정리하였습니다. * **refactor: Chip 설정 및 모델 구조 개선** * `PrezelChipModels.kt`와 `PrezelChipDefaults.kt`를 `config` 패키지로 이동하여 구조화했습니다. * `CompositionLocal`(`LocalPrezelChipColors` 등)을 통한 상태 전달 방식을 제거하고, `config` 객체를 직접 전달하거나 확장 함수를 통해 속성을 적용하도록 변경했습니다. * `PrezelChipDefault.withCustomColors` 확장 함수를 추가하여 사용자 정의 색상 적용 로직을 캡슐화했습니다. * **refactor: PrezelChip 및 PrezelIconChip 구현 최적화** * `PrezelChip`의 중복 정의된 함수를 통합하고, 실제 UI 렌더링을 담당하는 `PrezelChipContent`를 분리했습니다. * `PrezelIconChip`에서 `config` 파라미터의 기본값 설정 로직을 개선했습니다. * 불필요한 `LocalTextStyle` 및 `LocalPrezelChipIconColor` 등의 사용을 제거하고 `config`에서 직접 값을 참조하도록 수정했습니다. * **style: 미리보기(Preview) 코드 통합 및 개선** * `PrezelChipPreview.kt` 파일을 삭제하고, 해당 로직을 각 컴포넌트 파일(`PrezelChip.kt`, `PrezelIconChip.kt`) 내부로 통합했습니다. * `PreviewParameterProvider`를 도입하여 다양한 `PrezelChipType`에 대한 미리보기를 효율적으로 구성했습니다. * 미리보기 레이아웃을 `PreviewSection`과 `PreviewValueRow`를 사용하는 일관된 스타일로 업데이트했습니다. --- .../designsystem/component/chip/PrezelChip.kt | 221 ++++++++++-------- .../component/chip/PrezelChipPreview.kt | 117 ---------- .../component/chip/PrezelIconChip.kt | 109 ++++++--- .../chip/{ => config}/PrezelChipDefaults.kt | 41 ++-- .../chip/{ => config}/PrezelChipModels.kt | 2 +- 5 files changed, 216 insertions(+), 274 deletions(-) delete mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt rename Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/{ => config}/PrezelChipDefaults.kt (86%) rename Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/{ => config}/PrezelChipModels.kt (95%) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt index c3f02730..37a0684d 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt @@ -8,16 +8,29 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Icon -import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.Dp +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipColors +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefault +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefaults +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipFeedback +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipInteraction +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipSize +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipType +import com.team.prezel.core.designsystem.component.chip.config.withCustomColors import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview +import com.team.prezel.core.designsystem.preview.PreviewSection +import com.team.prezel.core.designsystem.preview.PreviewValueRow +import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelChip( @@ -35,10 +48,29 @@ fun PrezelChip( interaction = interaction, feedback = feedback, ), + customColors: PrezelChipColors? = null, +) { + require(text != null || iconResId != null) { + "Chip은 text 또는 icon 중 하나는 반드시 필요합니다." + } + + PrezelChipContent( + modifier = modifier, + text = text, + iconResId = iconResId, + config = config.withCustomColors(customColors ?: PrezelChipColors()), + ) +} + +@Composable +private fun PrezelChipContent( + modifier: Modifier = Modifier, + text: String?, + @DrawableRes iconResId: Int?, + config: PrezelChipDefault, ) { val hasText = text != null val hasIcon = iconResId != null - require(hasText || hasIcon) { "Chip은 text 또는 icon 중 하나는 반드시 필요합니다." } Surface( modifier = modifier, @@ -46,123 +78,118 @@ fun PrezelChip( color = config.containerColor, border = config.borderStroke, ) { - CompositionLocalProvider( - LocalTextStyle provides config.textStyle, - LocalPrezelChipIconColor provides config.iconColor, - LocalPrezelChipTextColor provides config.textColor, + Row( + modifier = Modifier.padding(config.contentPadding), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, ) { - Row( - modifier = Modifier.padding(config.contentPadding), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - ) { - iconResId?.let { resId -> - PrezelChipIcon(iconResId = resId, config = config) - } + iconResId?.let { resId -> + PrezelChipIcon( + iconResId = resId, + iconSize = config.iconSize, + tint = config.iconColor, + ) + } - if (hasText) { - if (hasIcon) { - Spacer(modifier = Modifier.width(config.iconTextSpacing)) - } - Text(text = text, color = LocalPrezelChipTextColor.current) + if (hasText) { + if (hasIcon) { + Spacer(modifier = Modifier.width(config.iconTextSpacing)) } + Text( + text = text, + color = config.textColor, + style = config.textStyle, + ) } } } } -@Composable -fun PrezelChip( - modifier: Modifier = Modifier, - text: String? = null, - @DrawableRes iconResId: Int? = null, - type: PrezelChipType = PrezelChipType.FILLED, - size: PrezelChipSize = PrezelChipSize.REGULAR, - interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, - feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, - config: PrezelChipDefault? = null, - customColors: PrezelChipColors = LocalPrezelChipColors.current, -) { - CompositionLocalProvider( - LocalPrezelChipColors provides customColors, - ) { - val resolvedConfig = - config ?: PrezelChipDefaults.getDefault( - iconOnly = text == null && iconResId != null, - type = type, - size = size, - interaction = interaction, - feedback = feedback, - ) - - PrezelChip( - modifier = modifier, - text = text, - iconResId = iconResId, - type = type, - size = size, - interaction = interaction, - feedback = feedback, - config = resolvedConfig, - ) - } -} - @Composable private fun PrezelChipIcon( @DrawableRes iconResId: Int, - config: PrezelChipDefault, + iconSize: Dp, + tint: Color, modifier: Modifier = Modifier, ) { Icon( painter = painterResource(id = iconResId), contentDescription = null, - modifier = modifier.size(config.iconSize), - tint = LocalPrezelChipIconColor.current, + modifier = modifier.size(iconSize), + tint = tint, ) } -@BasicPreview -@Composable -private fun PrezelChipSizePreview() { - PrezelChipSizePreviewContent { type, size -> - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - type = type, - size = size, - ) - } +private class PrezelChipTypeProvider : PreviewParameterProvider { + override val values: Sequence = PrezelChipType.entries.asSequence() } @BasicPreview @Composable -private fun PrezelChipInteractionPreview() { - PrezelChipInteractionPreviewContent { type, interaction -> - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - type = type, - interaction = interaction, - ) - } -} +private fun PrezelChipPreview( + @PreviewParameter(PrezelChipTypeProvider::class) type: PrezelChipType, +) { + PreviewSection(title = "Chip - $type") { + Text(text = "Size", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Regular") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + size = PrezelChipSize.REGULAR, + ) + } + PreviewValueRow(name = "Small") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + size = PrezelChipSize.SMALL, + ) + } -@BasicPreview -@Composable -private fun PrezelChipFeedbackPreview() { - PrezelChipFeedbackPreviewContent { type, feedback -> - PrezelChip( - text = "Label", - iconResId = PrezelIcons.Blank, - type = type, - feedback = feedback, - ) - } -} + Text(text = "Interaction", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Default") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.DEFAULT, + ) + } + PreviewValueRow(name = "Active") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.ACTIVE, + ) + } + PreviewValueRow(name = "Disabled") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.DISABLED, + ) + } -@BasicPreview -@Composable -private fun PrezelChipCustomPreview() { - PrezelChipCustomPreviewContent() + Text(text = "Feedback", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Default") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + feedback = PrezelChipFeedback.DEFAULT, + ) + } + PreviewValueRow(name = "Bad") { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + type = type, + feedback = PrezelChipFeedback.BAD, + ) + } + } } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt deleted file mode 100644 index 22577372..00000000 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipPreview.kt +++ /dev/null @@ -1,117 +0,0 @@ -package com.team.prezel.core.designsystem.component.chip - -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import com.team.prezel.core.designsystem.icon.PrezelIcons -import com.team.prezel.core.designsystem.preview.PreviewRow -import com.team.prezel.core.designsystem.preview.PreviewSection -import com.team.prezel.core.designsystem.preview.PreviewValueRow -import com.team.prezel.core.designsystem.theme.PrezelTheme - -@Composable -private fun PrezelChipPreviewContent( - previewTitle: String, - previewDescription: String, - values: List, - valueLabel: (T) -> String = { it.toString() }, - content: @Composable (PrezelChipType, T) -> Unit, -) { - PreviewSection( - title = previewTitle, - description = previewDescription, - ) { - PrezelChipType.entries.forEach { type -> - values.forEach { value -> - PreviewValueRow( - name = type.name, - valueLabel = valueLabel(value), - ) { - content(type, value) - } - } - } - } -} - -@Composable -internal fun PrezelChipSizePreviewContent(content: @Composable (PrezelChipType, PrezelChipSize) -> Unit) { - PrezelChipPreviewContent( - previewTitle = "Chip / Size", - previewDescription = "Chip의 크기를 조절합니다.", - values = PrezelChipSize.entries, - valueLabel = { it.name }, - content = content, - ) -} - -@Composable -internal fun PrezelChipInteractionPreviewContent(content: @Composable (PrezelChipType, PrezelChipInteraction) -> Unit) { - PrezelChipPreviewContent( - previewTitle = "Chip / Interaction", - previewDescription = "Chip의 상호작용 상태를 조절합니다.", - values = PrezelChipInteraction.entries, - valueLabel = { it.name }, - content = content, - ) -} - -@Composable -internal fun PrezelChipFeedbackPreviewContent(content: @Composable (PrezelChipType, PrezelChipFeedback) -> Unit) { - PrezelChipPreviewContent( - previewTitle = "Chip / Feedback", - previewDescription = "Chip의 피드백 상태를 조절합니다.", - values = PrezelChipFeedback.entries, - valueLabel = { it.name }, - content = content, - ) -} - -@Composable -internal fun PrezelChipCustomPreviewContent() { - PreviewSection( - title = "Chip / Custom", - description = "사용자 정의된 색 지정이 가능합니다.", - ) { - PreviewRow { - PrezelChip( - text = "느려요", - iconResId = PrezelIcons.Blank, - type = PrezelChipType.FILLED, - size = PrezelChipSize.REGULAR, - interaction = PrezelChipInteraction.DISABLED, - feedback = PrezelChipFeedback.BAD, - customColors = PrezelChipColors( - containerColor = PrezelTheme.colors.feedbackWarningSmall, - iconColor = PrezelTheme.colors.feedbackWarningRegular, - textColor = PrezelTheme.colors.feedbackWarningRegular, - ), - ) - - PrezelChip( - text = "빨라요", - type = PrezelChipType.OUTLINED, - size = PrezelChipSize.REGULAR, - interaction = PrezelChipInteraction.DEFAULT, - feedback = PrezelChipFeedback.DEFAULT, - customColors = PrezelChipColors( - containerColor = PrezelTheme.colors.feedbackBadSmall, - borderColor = PrezelTheme.colors.feedbackBadRegular, - iconColor = PrezelTheme.colors.feedbackBadRegular, - textColor = PrezelTheme.colors.feedbackBadRegular, - ), - ) - - PrezelChip( - text = "적당해요", - type = PrezelChipType.FILLED, - size = PrezelChipSize.SMALL, - interaction = PrezelChipInteraction.ACTIVE, - feedback = PrezelChipFeedback.DEFAULT, - customColors = PrezelChipColors( - containerColor = Color(0xFFDBFFF6), - textColor = Color(0xFF00A37A), - ), - ) - } - } -} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt index 6bf415d2..d4029840 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt @@ -1,10 +1,22 @@ package com.team.prezel.core.designsystem.component.chip import androidx.annotation.DrawableRes +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefault +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefaults +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipFeedback +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipInteraction +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipSize +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipType import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview +import com.team.prezel.core.designsystem.preview.PreviewSection +import com.team.prezel.core.designsystem.preview.PreviewValueRow +import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelIconChip( @@ -14,16 +26,14 @@ fun PrezelIconChip( size: PrezelChipSize = PrezelChipSize.REGULAR, interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, - config: PrezelChipDefault? = null, -) { - val resolvedConfig = config ?: PrezelChipDefaults.getDefault( + config: PrezelChipDefault = PrezelChipDefaults.getDefault( iconOnly = true, type = type, size = size, interaction = interaction, feedback = feedback, - ) - + ), +) { PrezelChip( modifier = modifier, iconResId = iconResId, @@ -31,42 +41,73 @@ fun PrezelIconChip( size = size, interaction = interaction, feedback = feedback, - config = resolvedConfig, + config = config, ) } -@BasicPreview -@Composable -private fun PrezelChipSizePreview() { - PrezelChipSizePreviewContent { type, size -> - PrezelIconChip( - iconResId = PrezelIcons.Blank, - type = type, - size = size, - ) - } +private class PrezelIconChipTypeProvider : PreviewParameterProvider { + override val values: Sequence = PrezelChipType.entries.asSequence() } @BasicPreview @Composable -private fun PrezelChipInteractionPreview() { - PrezelChipInteractionPreviewContent { type, interaction -> - PrezelIconChip( - iconResId = PrezelIcons.Blank, - type = type, - interaction = interaction, - ) - } -} +private fun PrezelChipPreview( + @PreviewParameter(PrezelIconChipTypeProvider::class) type: PrezelChipType, +) { + PreviewSection(title = "Chip - $type") { + Text(text = "Size", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Regular") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + size = PrezelChipSize.REGULAR, + ) + } + PreviewValueRow(name = "Small") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + size = PrezelChipSize.SMALL, + ) + } -@BasicPreview -@Composable -private fun PrezelChipFeedbackPreview() { - PrezelChipFeedbackPreviewContent { type, feedback -> - PrezelIconChip( - iconResId = PrezelIcons.Blank, - type = type, - feedback = feedback, - ) + Text(text = "Interaction", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Default") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.DEFAULT, + ) + } + PreviewValueRow(name = "Active") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.ACTIVE, + ) + } + PreviewValueRow(name = "Disabled") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + interaction = PrezelChipInteraction.DISABLED, + ) + } + + Text(text = "Feedback", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) + PreviewValueRow(name = "Default") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + feedback = PrezelChipFeedback.DEFAULT, + ) + } + PreviewValueRow(name = "Bad") { + PrezelChip( + iconResId = PrezelIcons.Blank, + type = type, + feedback = PrezelChipFeedback.BAD, + ) + } } } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt similarity index 86% rename from Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt rename to Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt index 5e81c44c..0e485eee 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipDefaults.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt @@ -1,10 +1,9 @@ -package com.team.prezel.core.designsystem.component.chip +package com.team.prezel.core.designsystem.component.chip.config import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable -import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.TextStyle @@ -12,16 +11,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.team.prezel.core.designsystem.theme.PrezelTheme -internal val LocalPrezelChipColors = staticCompositionLocalOf { PrezelChipColors() } - -internal val LocalPrezelChipTextColor = staticCompositionLocalOf { - error("No PrezelChipTextColor provided") -} - -internal val LocalPrezelChipIconColor = staticCompositionLocalOf { - error("No PrezelChipIconColor provided") -} - @Immutable data class PrezelChipColors( val containerColor: Color = Color.Unspecified, @@ -51,13 +40,11 @@ object PrezelChipDefaults { size: PrezelChipSize = PrezelChipSize.REGULAR, interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, - chipColors: PrezelChipColors = LocalPrezelChipColors.current, shape: Shape = getShape(size = size), borderStroke: BorderStroke? = getBorderStroke( type = type, interaction = interaction, feedback = feedback, - chipColors = chipColors, ), textStyle: TextStyle = getTextStyle(size = size), containerColor: Color = getContainerColor( @@ -65,19 +52,16 @@ object PrezelChipDefaults { type = type, interaction = interaction, feedback = feedback, - chipColors = chipColors, ), iconColor: Color = getIconColor( type = type, interaction = interaction, feedback = feedback, - chipColors = chipColors, ), textColor: Color = getTextColor( type = type, interaction = interaction, feedback = feedback, - chipColors = chipColors, ), contentPadding: PaddingValues = getContentPadding(size = size, iconOnly = iconOnly), iconTextSpacing: Dp = getIconTextSpacing(size = size), @@ -106,13 +90,11 @@ object PrezelChipDefaults { type: PrezelChipType, interaction: PrezelChipInteraction, feedback: PrezelChipFeedback, - chipColors: PrezelChipColors, ): BorderStroke? { if (type == PrezelChipType.FILLED) return null val borderColor = when { - chipColors.borderColor != Color.Unspecified -> chipColors.borderColor feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.borderRegular @@ -138,14 +120,12 @@ object PrezelChipDefaults { type: PrezelChipType, interaction: PrezelChipInteraction, feedback: PrezelChipFeedback, - chipColors: PrezelChipColors, ): Color { if (type == PrezelChipType.OUTLINED && iconOnly) { return Color.Transparent } return when { - chipColors.containerColor != Color.Unspecified -> chipColors.containerColor feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadSmall interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveXSmall interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.bgDisabled @@ -163,10 +143,8 @@ object PrezelChipDefaults { type: PrezelChipType, interaction: PrezelChipInteraction, feedback: PrezelChipFeedback, - chipColors: PrezelChipColors, ): Color = when { - chipColors.iconColor != Color.Unspecified -> chipColors.iconColor feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.iconDisabled @@ -183,10 +161,8 @@ object PrezelChipDefaults { type: PrezelChipType, interaction: PrezelChipInteraction, feedback: PrezelChipFeedback, - chipColors: PrezelChipColors, ): Color = when { - chipColors.textColor != Color.Unspecified -> chipColors.textColor feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.textDisabled @@ -237,3 +213,18 @@ object PrezelChipDefaults { PrezelChipSize.REGULAR -> 16.dp } } + +internal fun PrezelChipDefault.withCustomColors(customColors: PrezelChipColors): PrezelChipDefault = + copy( + borderStroke = when { + borderStroke == null -> null + customColors.borderColor == Color.Unspecified -> borderStroke + else -> BorderStroke( + width = borderStroke.width, + color = customColors.borderColor, + ) + }, + containerColor = if (customColors.containerColor != Color.Unspecified) customColors.containerColor else containerColor, + iconColor = if (customColors.iconColor != Color.Unspecified) customColors.iconColor else iconColor, + textColor = if (customColors.textColor != Color.Unspecified) customColors.textColor else textColor, + ) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipModels.kt similarity index 95% rename from Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt rename to Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipModels.kt index 16ca4f1e..7f150a8b 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChipModels.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipModels.kt @@ -1,4 +1,4 @@ -package com.team.prezel.core.designsystem.component.chip +package com.team.prezel.core.designsystem.component.chip.config import androidx.compose.runtime.Immutable From 2f6deb985bc281edc00e199dd2794ca5823b1e52 Mon Sep 17 00:00:00 2001 From: moondev03 Date: Wed, 8 Apr 2026 21:31:49 +0900 Subject: [PATCH 09/10] =?UTF-8?q?refactor:=20PrezelChip=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20=EB=B0=8F=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelChip`과 `PrezelIconChip`의 공통 UI 렌더링 로직을 `PrezelChipLayout`으로 통합하고, 커스텀 스타일 적용 방식을 개선했습니다. --- .../designsystem/component/chip/PrezelChip.kt | 136 +++++++----------- .../component/chip/PrezelIconChip.kt | 69 +++++++-- .../chip/config/PrezelChipDefaults.kt | 60 ++------ .../component/chip/config/PrezelChipLayout.kt | 79 ++++++++++ 4 files changed, 206 insertions(+), 138 deletions(-) create mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipLayout.kt diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt index 37a0684d..3d1db98f 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelChip.kt @@ -1,122 +1,47 @@ package com.team.prezel.core.designsystem.component.chip import androidx.annotation.DrawableRes -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Icon -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import androidx.compose.ui.unit.Dp -import com.team.prezel.core.designsystem.component.chip.config.PrezelChipColors import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefault import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefaults import com.team.prezel.core.designsystem.component.chip.config.PrezelChipFeedback import com.team.prezel.core.designsystem.component.chip.config.PrezelChipInteraction +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipLayout import com.team.prezel.core.designsystem.component.chip.config.PrezelChipSize import com.team.prezel.core.designsystem.component.chip.config.PrezelChipType -import com.team.prezel.core.designsystem.component.chip.config.withCustomColors import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview +import com.team.prezel.core.designsystem.preview.PreviewRow import com.team.prezel.core.designsystem.preview.PreviewSection import com.team.prezel.core.designsystem.preview.PreviewValueRow import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelChip( + text: String, modifier: Modifier = Modifier, - text: String? = null, @DrawableRes iconResId: Int? = null, type: PrezelChipType = PrezelChipType.FILLED, size: PrezelChipSize = PrezelChipSize.REGULAR, interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, config: PrezelChipDefault = PrezelChipDefaults.getDefault( - iconOnly = text == null && iconResId != null, + iconOnly = false, type = type, size = size, interaction = interaction, feedback = feedback, ), - customColors: PrezelChipColors? = null, ) { - require(text != null || iconResId != null) { - "Chip은 text 또는 icon 중 하나는 반드시 필요합니다." - } - - PrezelChipContent( + PrezelChipLayout( modifier = modifier, text = text, iconResId = iconResId, - config = config.withCustomColors(customColors ?: PrezelChipColors()), - ) -} - -@Composable -private fun PrezelChipContent( - modifier: Modifier = Modifier, - text: String?, - @DrawableRes iconResId: Int?, - config: PrezelChipDefault, -) { - val hasText = text != null - val hasIcon = iconResId != null - - Surface( - modifier = modifier, - shape = config.shape, - color = config.containerColor, - border = config.borderStroke, - ) { - Row( - modifier = Modifier.padding(config.contentPadding), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - ) { - iconResId?.let { resId -> - PrezelChipIcon( - iconResId = resId, - iconSize = config.iconSize, - tint = config.iconColor, - ) - } - - if (hasText) { - if (hasIcon) { - Spacer(modifier = Modifier.width(config.iconTextSpacing)) - } - Text( - text = text, - color = config.textColor, - style = config.textStyle, - ) - } - } - } -} - -@Composable -private fun PrezelChipIcon( - @DrawableRes iconResId: Int, - iconSize: Dp, - tint: Color, - modifier: Modifier = Modifier, -) { - Icon( - painter = painterResource(id = iconResId), - contentDescription = null, - modifier = modifier.size(iconSize), - tint = tint, + config = config, ) } @@ -193,3 +118,52 @@ private fun PrezelChipPreview( } } } + +@BasicPreview +@Composable +private fun PrezelChipCustomPreview( + @PreviewParameter(PrezelChipTypeProvider::class) type: PrezelChipType, +) { + PreviewSection(title = "Custom Chip - $type") { + PreviewRow { + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = false, + type = type, + containerColor = PrezelTheme.colors.accentPurpleSmall, + iconColor = PrezelTheme.colors.accentPurpleRegular, + textColor = PrezelTheme.colors.accentPurpleRegular, + borderColor = PrezelTheme.colors.accentPurpleRegular, + ), + ) + + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = false, + type = type, + containerColor = PrezelTheme.colors.accentTealSmall, + iconColor = PrezelTheme.colors.accentTealRegular, + textColor = PrezelTheme.colors.accentTealRegular, + borderColor = PrezelTheme.colors.accentTealRegular, + ), + ) + + PrezelChip( + text = "Label", + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = false, + type = type, + containerColor = PrezelTheme.colors.accentMagentaSmall, + iconColor = PrezelTheme.colors.accentMagentaRegular, + textColor = PrezelTheme.colors.accentMagentaRegular, + borderColor = PrezelTheme.colors.accentMagentaRegular, + ), + ) + } + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt index d4029840..368dac74 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/PrezelIconChip.kt @@ -10,10 +10,12 @@ import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefault import com.team.prezel.core.designsystem.component.chip.config.PrezelChipDefaults import com.team.prezel.core.designsystem.component.chip.config.PrezelChipFeedback import com.team.prezel.core.designsystem.component.chip.config.PrezelChipInteraction +import com.team.prezel.core.designsystem.component.chip.config.PrezelChipLayout import com.team.prezel.core.designsystem.component.chip.config.PrezelChipSize import com.team.prezel.core.designsystem.component.chip.config.PrezelChipType import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.BasicPreview +import com.team.prezel.core.designsystem.preview.PreviewRow import com.team.prezel.core.designsystem.preview.PreviewSection import com.team.prezel.core.designsystem.preview.PreviewValueRow import com.team.prezel.core.designsystem.theme.PrezelTheme @@ -34,13 +36,10 @@ fun PrezelIconChip( feedback = feedback, ), ) { - PrezelChip( + PrezelChipLayout( modifier = modifier, + text = null, iconResId = iconResId, - type = type, - size = size, - interaction = interaction, - feedback = feedback, config = config, ) } @@ -57,14 +56,14 @@ private fun PrezelChipPreview( PreviewSection(title = "Chip - $type") { Text(text = "Size", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) PreviewValueRow(name = "Regular") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, size = PrezelChipSize.REGULAR, ) } PreviewValueRow(name = "Small") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, size = PrezelChipSize.SMALL, @@ -73,21 +72,21 @@ private fun PrezelChipPreview( Text(text = "Interaction", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) PreviewValueRow(name = "Default") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, interaction = PrezelChipInteraction.DEFAULT, ) } PreviewValueRow(name = "Active") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, interaction = PrezelChipInteraction.ACTIVE, ) } PreviewValueRow(name = "Disabled") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, interaction = PrezelChipInteraction.DISABLED, @@ -96,14 +95,14 @@ private fun PrezelChipPreview( Text(text = "Feedback", style = PrezelTheme.typography.title2Medium, color = PrezelTheme.colors.textLarge) PreviewValueRow(name = "Default") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, feedback = PrezelChipFeedback.DEFAULT, ) } PreviewValueRow(name = "Bad") { - PrezelChip( + PrezelIconChip( iconResId = PrezelIcons.Blank, type = type, feedback = PrezelChipFeedback.BAD, @@ -111,3 +110,49 @@ private fun PrezelChipPreview( } } } + +@BasicPreview +@Composable +private fun PrezelChipCustomPreview( + @PreviewParameter(PrezelIconChipTypeProvider::class) type: PrezelChipType, +) { + PreviewSection(title = "Custom Chip - $type") { + PreviewRow { + PrezelIconChip( + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = true, + type = type, + containerColor = PrezelTheme.colors.accentPurpleSmall, + iconColor = PrezelTheme.colors.accentPurpleRegular, + textColor = PrezelTheme.colors.accentPurpleRegular, + borderColor = PrezelTheme.colors.accentPurpleRegular, + ), + ) + + PrezelIconChip( + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = true, + type = type, + containerColor = PrezelTheme.colors.accentTealSmall, + iconColor = PrezelTheme.colors.accentTealRegular, + textColor = PrezelTheme.colors.accentTealRegular, + borderColor = PrezelTheme.colors.accentTealRegular, + ), + ) + + PrezelIconChip( + iconResId = PrezelIcons.Blank, + config = PrezelChipDefaults.getDefault( + iconOnly = true, + type = type, + containerColor = PrezelTheme.colors.accentMagentaSmall, + iconColor = PrezelTheme.colors.accentMagentaRegular, + textColor = PrezelTheme.colors.accentMagentaRegular, + borderColor = PrezelTheme.colors.accentMagentaRegular, + ), + ) + } + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt index 0e485eee..860a59d2 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt @@ -1,6 +1,5 @@ package com.team.prezel.core.designsystem.component.chip.config -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable @@ -11,22 +10,14 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.team.prezel.core.designsystem.theme.PrezelTheme -@Immutable -data class PrezelChipColors( - val containerColor: Color = Color.Unspecified, - val borderColor: Color = Color.Unspecified, - val iconColor: Color = Color.Unspecified, - val textColor: Color = Color.Unspecified, -) - @Immutable data class PrezelChipDefault( val shape: Shape, - val borderStroke: BorderStroke?, val textStyle: TextStyle, val containerColor: Color, val iconColor: Color, val textColor: Color, + val borderColor: Color?, val contentPadding: PaddingValues, val iconTextSpacing: Dp, val iconSize: Dp, @@ -41,11 +32,6 @@ object PrezelChipDefaults { interaction: PrezelChipInteraction = PrezelChipInteraction.DEFAULT, feedback: PrezelChipFeedback = PrezelChipFeedback.DEFAULT, shape: Shape = getShape(size = size), - borderStroke: BorderStroke? = getBorderStroke( - type = type, - interaction = interaction, - feedback = feedback, - ), textStyle: TextStyle = getTextStyle(size = size), containerColor: Color = getContainerColor( iconOnly = iconOnly, @@ -63,16 +49,21 @@ object PrezelChipDefaults { interaction = interaction, feedback = feedback, ), + borderColor: Color? = getBorderColor( + type = type, + interaction = interaction, + feedback = feedback, + ), contentPadding: PaddingValues = getContentPadding(size = size, iconOnly = iconOnly), iconTextSpacing: Dp = getIconTextSpacing(size = size), iconSize: Dp = getIconSize(size = size), ) = PrezelChipDefault( shape = shape, - borderStroke = borderStroke, textStyle = textStyle, containerColor = containerColor, iconColor = iconColor, textColor = textColor, + borderColor = borderColor, contentPadding = contentPadding, iconTextSpacing = iconTextSpacing, iconSize = iconSize, @@ -86,25 +77,19 @@ object PrezelChipDefaults { } @Composable - private fun getBorderStroke( + private fun getBorderColor( type: PrezelChipType, interaction: PrezelChipInteraction, feedback: PrezelChipFeedback, - ): BorderStroke? { + ): Color? { if (type == PrezelChipType.FILLED) return null - val borderColor = - when { - feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular - interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular - interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.borderRegular - else -> PrezelTheme.colors.borderMedium - } - - return BorderStroke( - width = PrezelTheme.stroke.V1, - color = borderColor, - ) + return when { + feedback == PrezelChipFeedback.BAD -> PrezelTheme.colors.feedbackBadRegular + interaction == PrezelChipInteraction.ACTIVE -> PrezelTheme.colors.interactiveRegular + interaction == PrezelChipInteraction.DISABLED -> PrezelTheme.colors.borderRegular + else -> PrezelTheme.colors.borderMedium + } } @Composable @@ -213,18 +198,3 @@ object PrezelChipDefaults { PrezelChipSize.REGULAR -> 16.dp } } - -internal fun PrezelChipDefault.withCustomColors(customColors: PrezelChipColors): PrezelChipDefault = - copy( - borderStroke = when { - borderStroke == null -> null - customColors.borderColor == Color.Unspecified -> borderStroke - else -> BorderStroke( - width = borderStroke.width, - color = customColors.borderColor, - ) - }, - containerColor = if (customColors.containerColor != Color.Unspecified) customColors.containerColor else containerColor, - iconColor = if (customColors.iconColor != Color.Unspecified) customColors.iconColor else iconColor, - textColor = if (customColors.textColor != Color.Unspecified) customColors.textColor else textColor, - ) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipLayout.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipLayout.kt new file mode 100644 index 00000000..1bfbb4d6 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipLayout.kt @@ -0,0 +1,79 @@ +package com.team.prezel.core.designsystem.component.chip.config + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.Dp +import com.team.prezel.core.designsystem.theme.PrezelTheme + +@Composable +internal fun PrezelChipLayout( + modifier: Modifier = Modifier, + text: String?, + @DrawableRes iconResId: Int?, + config: PrezelChipDefault, +) { + require(text != null || iconResId != null) { "Chip은 text 또는 icon 중 하나는 반드시 필요합니다." } + + Surface( + modifier = modifier, + shape = config.shape, + color = config.containerColor, + border = config.borderColor?.let { color -> + BorderStroke(width = PrezelTheme.stroke.V1, color = color) + }, + ) { + Row( + modifier = Modifier.padding(config.contentPadding), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + iconResId?.let { resId -> + PrezelChipIcon( + iconResId = resId, + iconSize = config.iconSize, + tint = config.iconColor, + ) + } + + if (text != null) { + if (iconResId != null) { + Spacer(modifier = Modifier.width(config.iconTextSpacing)) + } + Text( + text = text, + color = config.textColor, + style = config.textStyle, + ) + } + } + } +} + +@Composable +private fun PrezelChipIcon( + @DrawableRes iconResId: Int, + iconSize: Dp, + tint: Color, + modifier: Modifier = Modifier, +) { + Icon( + painter = painterResource(id = iconResId), + contentDescription = null, + modifier = modifier.size(iconSize), + tint = tint, + ) +} From 218a5e3e650bd82af777641dac3730b3a8c50e6d Mon Sep 17 00:00:00 2001 From: moondev03 Date: Wed, 8 Apr 2026 21:37:23 +0900 Subject: [PATCH 10/10] =?UTF-8?q?refactor:=20PrezelChip=20=ED=85=8C?= =?UTF-8?q?=EB=91=90=EB=A6=AC=20=EC=83=89=EC=83=81=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelChipType에 따른 borderColor 조건부 적용 `PrezelChipDefaults`에서 `borderColor`를 설정할 때, 칩의 타입이 `PrezelChipType.OUTLINED`인 경우에만 색상을 할당하고 그 외의 경우에는 `null`이 전달되도록 로직을 수정하였습니다. --- .../designsystem/component/chip/config/PrezelChipDefaults.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt index 860a59d2..c839bbef 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/chip/config/PrezelChipDefaults.kt @@ -63,7 +63,7 @@ object PrezelChipDefaults { containerColor = containerColor, iconColor = iconColor, textColor = textColor, - borderColor = borderColor, + borderColor = if (type == PrezelChipType.OUTLINED) borderColor else null, contentPadding = contentPadding, iconTextSpacing = iconTextSpacing, iconSize = iconSize,