From 69b60bb7a24aab11befbb6758d1a5e3b55786519 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Sun, 8 Feb 2026 21:47:15 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20PrezelAccordion=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 디자인시스템에 아코디언 컴포넌트인 `PrezelAccordion`을 새롭게 추가했습니다. * `AnimatedVisibility`를 이용한 펼치기/접기 애니메이션 구현 * 헤더, 라벨, 콘텐츠 영역을 커스텀할 수 있는 슬롯 구조 적용 * `showDivider` 옵션을 통한 구분선 표시 기능 제공 * 상태별 미리보기(Collapsed, Expanded, Interactive) 추가 --- .../designsystem/component/PrezelAccordion.kt | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt new file mode 100644 index 00000000..a5b52525 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -0,0 +1,273 @@ +package com.team.prezel.core.designsystem.component + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +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.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.team.prezel.core.designsystem.R +import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles +import com.team.prezel.core.designsystem.preview.PreviewScaffold +import com.team.prezel.core.designsystem.preview.ThemePreview +import com.team.prezel.core.designsystem.theme.PrezelTheme + +@Composable +fun PrezelAccordion( + modifier: Modifier = Modifier, + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, + enabled: Boolean = true, + showDivider: Boolean = false, + header: @Composable (expanded: Boolean) -> Unit, + label: @Composable (expanded: Boolean) -> Unit, + content: @Composable () -> Unit, +) { + val rotation by animateFloatAsState( + targetValue = if (expanded) 180f else 0f, + label = "accordionChevronRotation", + ) + + Surface( + modifier = modifier, + color = Color.Transparent, + ) { + Column { + PrezelAccordionHeader( + enabled = enabled, + onClick = { onExpandedChange(!expanded) }, + header = { header(expanded) }, + label = { label(expanded) }, + chevron = { PrezelAccordionChevron(rotation = rotation) }, + ) + + PrezelAccordionDivider(showDivider = showDivider) + + PrezelAccordionContent( + expanded = expanded, + content = content, + ) + } + } +} + +@Composable +private fun PrezelAccordionHeader( + enabled: Boolean, + onClick: () -> Unit, + header: @Composable () -> Unit, + label: @Composable () -> Unit, + chevron: @Composable () -> Unit, +) { + Row( + modifier = Modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 48.dp) + .clickable( + enabled = enabled, + indication = null, + interactionSource = remember { MutableInteractionSource() }, + onClick = onClick, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + Box( + modifier = Modifier + .weight(1f) + ) { + header() + } + Spacer(Modifier.width(8.dp)) + + label() + + Spacer(Modifier.width(8.dp)) + + chevron() + } +} + +@Composable +private fun PrezelAccordionChevron(rotation: Float) { + Icon( + painter = painterResource(R.drawable.core_designsystem_ic_chevron_down), + contentDescription = null, + modifier = Modifier + .size(24.dp) + .rotate(rotation), + tint = PrezelTheme.colors.iconRegular, + ) +} + +@Composable +private fun PrezelAccordionDivider(showDivider: Boolean) { + if (!showDivider) return + + PrezelHorizontalDivider( + type = PrezelDividerType.THICK, + color = PrezelTheme.colors.borderSmall, + ) +} + +@Composable +private fun PrezelAccordionContent( + expanded: Boolean, + content: @Composable () -> Unit, +) { + AnimatedVisibility( + visible = expanded, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically(), + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + ) { + content() + } + } +} + +@ThemePreview +@Composable +private fun PrezelAccordionPreview_Collapsed() { + PrezelTheme { + PreviewScaffold { + PrezelAccordion( + expanded = false, + onExpandedChange = {}, + showDivider = true, + header = { + Text( + text = "Title", + style = PrezelTextStyles.Body2Medium.toTextStyle(), + color = PrezelTheme.colors.textLarge, + ) + }, + label = { + Text( + text = "Label", + style = PrezelTextStyles.Body2Bold.toTextStyle(), + color = PrezelTheme.colors.interactiveRegular, + ) + }, + ) { + Text( + text = "Content", + style = PrezelTextStyles.Body3Regular.toTextStyle(), + color = PrezelTheme.colors.textRegular, + ) + } + } + } +} + +@ThemePreview +@Composable +private fun PrezelAccordionPreview_Expanded() { + PrezelTheme { + PreviewScaffold { + PrezelAccordion( + expanded = true, + onExpandedChange = {}, + showDivider = true, + header = { + Text( + text = "Title", + modifier = Modifier.padding(start = 12.dp), + style = PrezelTextStyles.Body2Medium.toTextStyle(), + color = PrezelTheme.colors.textLarge, + ) + }, + label = { + Text( + text = "Label", + style = PrezelTextStyles.Body2Bold.toTextStyle(), + color = PrezelTheme.colors.interactiveRegular, + ) + }, + ) { + Text( + text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", + style = PrezelTextStyles.Caption2Medium.toTextStyle(), + color = PrezelTheme.colors.textLarge, + ) + } + } + } +} + +@ThemePreview +@Composable +private fun PrezelAccordionPreview_Interactive() { + PrezelTheme { + var expanded by remember { mutableStateOf(false) } + + PreviewScaffold { + PrezelAccordion( + expanded = expanded, + onExpandedChange = { expanded = it }, + showDivider = true, + header = { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + PrezelCheckbox( + checked = false, + size = CheckboxSize.REGULAR, + onCheckedChange = {}, + ) + + Spacer(Modifier.width(4.dp)) + + Text( + text = "(필수) 이용약관", + modifier = Modifier.weight(1f), + style = PrezelTextStyles.Body3Medium.toTextStyle(), + color = PrezelTheme.colors.textLarge, + ) + } + }, + label = { + Text( + text = "자세히 보기", + style = PrezelTextStyles.Caption2Medium.toTextStyle(), + color = PrezelTheme.colors.textMedium, + ) + }, + ) { + Text( + text = "클릭하면 열리고 닫힙니다.", + style = PrezelTextStyles.Caption2Medium.toTextStyle(), + color = PrezelTheme.colors.textLarge, + ) + } + } + } +} From 6046ac426c6ce6a7658db6e64770d660fa6c8aab Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Sun, 8 Feb 2026 22:08:13 +0900 Subject: [PATCH 02/11] =?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=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B0=8F=20=EC=8B=A0?= =?UTF-8?q?=EA=B7=9C=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 아이콘 세트를 전반적으로 업데이트하고, 명명 규칙을 통일했습니다. * 신규 아이콘 추가: `Menu`, `Search`, `Upload`, `Lock`, `Storage`, `QuestionCircle` 등 * 기존 아이콘 리팩토링: `Calendar`, `Balloon`, `Check`, `Person`, `Video` 등 벡터 패스 및 색상 수정 * 아이콘 명명 규칙 변경: `WarningCircle` -> `WarningCircleOutlined` 등 형태에 따른 접미사 추가 * `PrezelIcons` 클래스 내 리소스 참조 업데이트 및 신규 아이콘 등록 * 불필요한 아이콘 삭제 (`ic_info`, `ic_warning`) 및 `PrezelAccordion` 코드 스타일 수정 --- .../designsystem/component/PrezelAccordion.kt | 2 +- .../core/designsystem/icon/PrezelIcons.kt | 17 +++++++++++++---- .../drawable/core_designsystem_ic_balloon.xml | 2 +- .../drawable/core_designsystem_ic_calendar.xml | 4 ++-- .../res/drawable/core_designsystem_ic_check.xml | 2 +- .../drawable/core_designsystem_ic_college.xml | 2 +- .../drawable/core_designsystem_ic_company.xml | 2 +- .../res/drawable/core_designsystem_ic_edit.xml | 5 +++-- .../drawable/core_designsystem_ic_gallery.xml | 2 +- .../res/drawable/core_designsystem_ic_hand.xml | 2 +- .../res/drawable/core_designsystem_ic_info.xml | 9 --------- .../core_designsystem_ic_info_circle_filled.xml | 9 +++++++++ ...re_designsystem_ic_info_circle_outlined.xml} | 0 .../res/drawable/core_designsystem_ic_lock.xml | 2 +- .../res/drawable/core_designsystem_ic_menu.xml | 9 +++++++++ .../res/drawable/core_designsystem_ic_mic.xml | 2 +- .../drawable/core_designsystem_ic_person.xml | 5 ++++- ...e_designsystem_ic_question_circle_filled.xml | 9 +++++++++ ...designsystem_ic_question_circle_outlined.xml | 9 +++++++++ .../drawable/core_designsystem_ic_search.xml | 9 +++++++++ .../drawable/core_designsystem_ic_setting.xml | 2 +- .../drawable/core_designsystem_ic_trophy.xml | 2 +- .../drawable/core_designsystem_ic_upload.xml | 9 +++++++++ .../res/drawable/core_designsystem_ic_video.xml | 2 +- .../res/drawable/core_designsystem_ic_voice.xml | 2 +- .../drawable/core_designsystem_ic_warning.xml | 9 --------- ...re_designsystem_ic_warning_circle_filled.xml | 10 ++++++++++ ...designsystem_ic_warning_circle_outlined.xml} | 0 28 files changed, 99 insertions(+), 40 deletions(-) delete mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_filled.xml rename Prezel/core/designsystem/src/main/res/drawable/{core_designsystem_ic_info_circle.xml => core_designsystem_ic_info_circle_outlined.xml} (100%) create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_menu.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_filled.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_outlined.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_search.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_upload.xml delete mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning.xml create mode 100644 Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_filled.xml rename Prezel/core/designsystem/src/main/res/drawable/{core_designsystem_ic_warning_circle.xml => core_designsystem_ic_warning_circle_outlined.xml} (100%) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index a5b52525..f1ff6b57 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -98,7 +98,7 @@ private fun PrezelAccordionHeader( ) { Box( modifier = Modifier - .weight(1f) + .weight(1f), ) { header() } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt index a6d7d6d2..63919d44 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt @@ -19,30 +19,39 @@ object PrezelIcons { val ChevronUp = R.drawable.core_designsystem_ic_chevron_up val College = R.drawable.core_designsystem_ic_college val Company = R.drawable.core_designsystem_ic_company + val Edit = R.drawable.core_designsystem_ic_edit val Folder = R.drawable.core_designsystem_ic_folder val Gallery = R.drawable.core_designsystem_ic_gallery val Hand = R.drawable.core_designsystem_ic_hand val Home = R.drawable.core_designsystem_ic_home - val Info = R.drawable.core_designsystem_ic_info - val InfoCircle = R.drawable.core_designsystem_ic_info_circle + val InfoCircleFilled = R.drawable.core_designsystem_ic_info_circle_filled + val InfoCircleOutlined = R.drawable.core_designsystem_ic_info_circle_outlined val Kakao = R.drawable.core_designsystem_ic_kakao + val Lock = R.drawable.core_designsystem_ic_lock + val Menu = R.drawable.core_designsystem_ic_menu val Mic = R.drawable.core_designsystem_ic_mic val Pause = R.drawable.core_designsystem_ic_pause val Person = R.drawable.core_designsystem_ic_person val Play = R.drawable.core_designsystem_ic_play val Plus = R.drawable.core_designsystem_ic_plus val Profile = R.drawable.core_designsystem_ic_profile + val QuestionCircleFilled = R.drawable.core_designsystem_ic_question_circle_filled + val QuestionCircleOutlined = R.drawable.core_designsystem_ic_question_circle_outlined val RadioCircleFilled = R.drawable.core_designsystem_ic_radio_circle_filled val RadioCircleOutlined = R.drawable.core_designsystem_ic_radio_circle_outlined val Recording = R.drawable.core_designsystem_ic_recording val Reset = R.drawable.core_designsystem_ic_reset val Rotate = R.drawable.core_designsystem_ic_rotate + val Search = R.drawable.core_designsystem_ic_search + val Setting = R.drawable.core_designsystem_ic_setting val Stop = R.drawable.core_designsystem_ic_stop + val Storage = R.drawable.core_designsystem_ic_storage val Trophy = R.drawable.core_designsystem_ic_trophy + val Upload = R.drawable.core_designsystem_ic_upload val Video = R.drawable.core_designsystem_ic_video val Voice = R.drawable.core_designsystem_ic_voice - val Warning = R.drawable.core_designsystem_ic_warning - val WarningCircle = R.drawable.core_designsystem_ic_warning_circle + val WarningCircleFilled = R.drawable.core_designsystem_ic_warning_circle_filled + val WarningCircleOutlined = R.drawable.core_designsystem_ic_warning_circle_outlined val ZoomIn = R.drawable.core_designsystem_ic_zoom_in val ZoomOut = R.drawable.core_designsystem_ic_zoom_out } diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_balloon.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_balloon.xml index 87216bfa..c79fac59 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_balloon.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_balloon.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml index 20b215d1..6a5912b2 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M21,18.5C21,19.881 19.881,21 18.5,21H5.5C4.119,21 3,19.881 3,18.5V10.5H21V18.5ZM15,1.999C15.414,1.999 15.75,2.335 15.75,2.749V4H18.5C19.881,4 21,5.119 21,6.5V9.5H3V6.5C3,5.119 4.119,4 5.5,4H8.25V2.749C8.25,2.335 8.586,1.999 9,1.999C9.414,1.999 9.75,2.335 9.75,2.749V4H14.25V2.749C14.25,2.335 14.586,1.999 15,1.999Z" + android:fillColor="#2F3238"/> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_check.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_check.xml index 27eb12b8..484f3834 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_check.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_check.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_college.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_college.xml index 7b7e4853..91569cdb 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_college.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_college.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_company.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_company.xml index 201249d0..c2312f83 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_company.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_company.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_edit.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_edit.xml index db98b7d2..8a0c4341 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_edit.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_edit.xml @@ -4,6 +4,7 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M16.744,11.257L7.294,20.707C7.107,20.894 6.852,21 6.587,21H4C3.448,21 3,20.552 3,20V17.413C3,17.148 3.106,16.894 3.293,16.706L12.743,7.256L16.744,11.257ZM16.413,3.586C17.194,2.805 18.462,2.805 19.243,3.586L20.414,4.758C21.195,5.539 21.195,6.806 20.414,7.587L17.451,10.549L13.45,6.549L16.413,3.586Z" + android:fillColor="#6E737D" + android:fillType="evenOdd"/> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_gallery.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_gallery.xml index a15f090f..91d11ae1 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_gallery.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_gallery.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_hand.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_hand.xml index 73619535..7a3ea16b 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_hand.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_hand.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info.xml deleted file mode 100644 index 18bc800c..00000000 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_filled.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_filled.xml new file mode 100644 index 00000000..66e7cc87 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_outlined.xml similarity index 100% rename from Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle.xml rename to Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_info_circle_outlined.xml diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_lock.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_lock.xml index 5fc1d5c3..1eda06a4 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_lock.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_lock.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_menu.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_menu.xml new file mode 100644 index 00000000..2ae1ee32 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_menu.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_mic.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_mic.xml index db4b90be..5d351126 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_mic.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_mic.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_person.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_person.xml index 16b31ae4..80f9aa10 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_person.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_person.xml @@ -4,6 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_filled.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_filled.xml new file mode 100644 index 00000000..3885a93e --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_outlined.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_outlined.xml new file mode 100644 index 00000000..7a5bd410 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_question_circle_outlined.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_search.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_search.xml new file mode 100644 index 00000000..8fba3a61 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_search.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_setting.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_setting.xml index b6092413..3d62e975 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_setting.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_setting.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_trophy.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_trophy.xml index ab791f33..319d71d0 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_trophy.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_trophy.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_upload.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_upload.xml new file mode 100644 index 00000000..86804f1e --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_upload.xml @@ -0,0 +1,9 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_video.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_video.xml index f8f79748..6aa1dde9 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_video.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_video.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_voice.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_voice.xml index ccf2e536..6bc789d7 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_voice.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_voice.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning.xml deleted file mode 100644 index 7bfd5675..00000000 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_filled.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_filled.xml new file mode 100644 index 00000000..f6703f38 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_filled.xml @@ -0,0 +1,10 @@ + + + diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_outlined.xml similarity index 100% rename from Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle.xml rename to Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_warning_circle_outlined.xml From 9ac31c80df28b40c5bc7f04799c095427b191d21 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Thu, 12 Feb 2026 12:13:35 +0900 Subject: [PATCH 03/11] =?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=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EB=B0=8F=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 아코디언 컴포넌트에 접근성 보조를 위한 content description 리소스를 추가하고 적용했습니다. * 아코디언 및 TopAppBar에 사용되는 아이콘 리소스를 `PrezelIcons` 상수로 교체했습니다. * 캘린더 아이콘의 색상을 수정했습니다(`2F3238` -> `6E737D`). * TopAppBar 프리뷰의 아이콘을 실제 아이콘으로 업데이트했습니다. --- .../core/designsystem/component/PrezelAccordion.kt | 13 +++++-------- .../prezel/core/designsystem/component/TopAppBar.kt | 10 +++++----- .../res/drawable/core_designsystem_ic_calendar.xml | 2 +- .../designsystem/src/main/res/values/strings.xml | 1 + 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index f1ff6b57..725b30fb 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -30,9 +30,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.team.prezel.core.designsystem.R import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles +import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.PreviewScaffold import com.team.prezel.core.designsystem.preview.ThemePreview import com.team.prezel.core.designsystem.theme.PrezelTheme @@ -115,8 +117,8 @@ private fun PrezelAccordionHeader( @Composable private fun PrezelAccordionChevron(rotation: Float) { Icon( - painter = painterResource(R.drawable.core_designsystem_ic_chevron_down), - contentDescription = null, + painter = painterResource(PrezelIcons.ChevronDown), + contentDescription = stringResource(R.string.core_designsystem_accordion_desc), modifier = Modifier .size(24.dp) .rotate(rotation), @@ -246,12 +248,7 @@ private fun PrezelAccordionPreview_Interactive() { Spacer(Modifier.width(4.dp)) - Text( - text = "(필수) 이용약관", - modifier = Modifier.weight(1f), - style = PrezelTextStyles.Body3Medium.toTextStyle(), - color = PrezelTheme.colors.textLarge, - ) + Text(text = "(필수) 이용약관") } }, label = { diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt index d14a7be9..c9f88d97 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt @@ -102,7 +102,7 @@ private fun PrezelTopAppBarWithAllIconsPreview() { leadingIcon = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Blank), + painter = painterResource(PrezelIcons.ArrowLeft), contentDescription = "뒤로가기", ) } @@ -110,14 +110,14 @@ private fun PrezelTopAppBarWithAllIconsPreview() { trailingIcons = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Blank), + painter = painterResource(PrezelIcons.Search), contentDescription = "검색", ) } IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Blank), - contentDescription = "더보기", + painter = painterResource(PrezelIcons.Menu), + contentDescription = "메뉴", ) } }, @@ -142,7 +142,7 @@ private fun PrezelTopAppBarScrollTestPreview() { leadingIcon = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Blank), + painter = painterResource(PrezelIcons.ArrowLeft), contentDescription = "뒤로가기", ) } diff --git a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml index 6a5912b2..88366171 100644 --- a/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml +++ b/Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_calendar.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> + android:fillColor="#6E737D"/> diff --git a/Prezel/core/designsystem/src/main/res/values/strings.xml b/Prezel/core/designsystem/src/main/res/values/strings.xml index 519ffa15..20945a7f 100644 --- a/Prezel/core/designsystem/src/main/res/values/strings.xml +++ b/Prezel/core/designsystem/src/main/res/values/strings.xml @@ -2,4 +2,5 @@ 플로팅 버튼 닫기 체크박스 + 아코디언 토글 From 6b1aa93309bc667f54a782cf742489557c1e024c Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Tue, 24 Feb 2026 16:22:29 +0900 Subject: [PATCH 04/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=B0=8F=20=EB=82=B4=EB=B6=80=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PrezelAccordion의 가독성과 유연성을 높이기 위해 파라미터 명칭을 변경하고 레이아웃을 조정하였습니다. * `label` 파라미터 명칭을 `trailingContent`로 변경하여 역할을 명확히 함 * `chevron` 파라미터 명칭을 `icon`으로 변경 * `onClick` 콜백 명칭을 `onTap`으로 변경 * 헤더 내부의 컴포넌트 간 간격(Spacer) 조정 및 레이아웃 최적화 * Preview 코드에 변경된 파라미터 명칭 반영 --- .../designsystem/component/PrezelAccordion.kt | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 725b30fb..85617bef 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -47,7 +47,7 @@ fun PrezelAccordion( enabled: Boolean = true, showDivider: Boolean = false, header: @Composable (expanded: Boolean) -> Unit, - label: @Composable (expanded: Boolean) -> Unit, + trailingContent: @Composable (expanded: Boolean) -> Unit, content: @Composable () -> Unit, ) { val rotation by animateFloatAsState( @@ -62,10 +62,10 @@ fun PrezelAccordion( Column { PrezelAccordionHeader( enabled = enabled, - onClick = { onExpandedChange(!expanded) }, + onTap = { onExpandedChange(!expanded) }, header = { header(expanded) }, - label = { label(expanded) }, - chevron = { PrezelAccordionChevron(rotation = rotation) }, + trailingContent = { trailingContent(expanded) }, + icon = { PrezelAccordionChevron(rotation = rotation) }, ) PrezelAccordionDivider(showDivider = showDivider) @@ -81,10 +81,10 @@ fun PrezelAccordion( @Composable private fun PrezelAccordionHeader( enabled: Boolean, - onClick: () -> Unit, + onTap: () -> Unit, header: @Composable () -> Unit, - label: @Composable () -> Unit, - chevron: @Composable () -> Unit, + trailingContent: @Composable () -> Unit, + icon: @Composable () -> Unit, ) { Row( modifier = Modifier @@ -94,23 +94,22 @@ private fun PrezelAccordionHeader( enabled = enabled, indication = null, interactionSource = remember { MutableInteractionSource() }, - onClick = onClick, + onClick = onTap, ), verticalAlignment = Alignment.CenterVertically, ) { Box( - modifier = Modifier - .weight(1f), + modifier = Modifier.weight(1f), ) { header() } - Spacer(Modifier.width(8.dp)) + Spacer(Modifier.width(12.dp)) - label() + trailingContent() Spacer(Modifier.width(8.dp)) - chevron() + icon() } } @@ -172,7 +171,7 @@ private fun PrezelAccordionPreview_Collapsed() { color = PrezelTheme.colors.textLarge, ) }, - label = { + trailingContent = { Text( text = "Label", style = PrezelTextStyles.Body2Bold.toTextStyle(), @@ -207,7 +206,7 @@ private fun PrezelAccordionPreview_Expanded() { color = PrezelTheme.colors.textLarge, ) }, - label = { + trailingContent = { Text( text = "Label", style = PrezelTextStyles.Body2Bold.toTextStyle(), @@ -251,7 +250,7 @@ private fun PrezelAccordionPreview_Interactive() { Text(text = "(필수) 이용약관") } }, - label = { + trailingContent = { Text( text = "자세히 보기", style = PrezelTextStyles.Caption2Medium.toTextStyle(), From 051ab7a1fe6081dc27d800564747ea0cea61204d Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Wed, 25 Feb 2026 13:57:57 +0900 Subject: [PATCH 05/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PrezelAccordion 하드코딩된 수치를 디자인 시스템 토큰으로 교체 `PrezelAccordion` 컴포넌트 내부에서 사용되던 하드코딩된 여백 값(`12.dp`, `8.dp`)을 `PrezelTheme.spacing` 토큰(`V12`, `V8`)으로 수정하였습니다. * style: strings.xml 리소스 위치 정렬 `core_designsystem_accordion_desc` 리소스의 위치를 가독성을 위해 상단으로 이동시켰습니다. --- .../prezel/core/designsystem/component/PrezelAccordion.kt | 6 +++--- Prezel/core/designsystem/src/main/res/values/strings.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 85617bef..4bddb964 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -103,11 +103,11 @@ private fun PrezelAccordionHeader( ) { header() } - Spacer(Modifier.width(12.dp)) + Spacer(Modifier.width(PrezelTheme.spacing.V12)) trailingContent() - Spacer(Modifier.width(8.dp)) + Spacer(Modifier.width(PrezelTheme.spacing.V8)) icon() } @@ -148,7 +148,7 @@ private fun PrezelAccordionContent( Column( modifier = Modifier .fillMaxWidth() - .padding(12.dp), + .padding(PrezelTheme.spacing.V12), ) { content() } diff --git a/Prezel/core/designsystem/src/main/res/values/strings.xml b/Prezel/core/designsystem/src/main/res/values/strings.xml index bea23a3c..f994348e 100644 --- a/Prezel/core/designsystem/src/main/res/values/strings.xml +++ b/Prezel/core/designsystem/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ + 아코디언 토글 플로팅 버튼 닫기 날짜 선택 닫기 체크박스 @@ -15,5 +16,4 @@ - 아코디언 토글 From 22372b89fa54357fd7823bd47d29489b0e8fc619 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Fri, 27 Feb 2026 00:12:42 +0900 Subject: [PATCH 06/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelAccordion` 컴포넌트의 내부 구조를 정리하고 여백 및 클릭 로직을 개선했습니다. * **구조 및 레이아웃 개선**: * `Surface`를 제거하고 `Modifier.background(Color.Transparent)`를 적용한 `Column`으로 변경했습니다. * `PrezelAccordionHeader` 내부의 패딩 설정을 조정하고, `PrezelAccordionContent`의 고정 패딩(`V12`)을 제거하여 외부에서 제어할 수 있도록 수정했습니다. * `PrezelAccordionChevron` 애니메이션 로직을 컴포넌트 내부로 캡슐화했습니다. * **코드 정리**: * `clickable`의 `interactionSource`를 `null`로 설정하여 불필요한 메모리 할당을 방지했습니다. * 컴포저블 파라미터 순서를 표준 가이드에 맞춰 조정했습니다. * Preview 코드 내의 불필요한 여백 및 스타일 적용 방식을 수정했습니다. --- .../designsystem/component/PrezelAccordion.kt | 75 ++++++++----------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 4bddb964..dc3fa699 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -6,8 +6,8 @@ import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -18,7 +18,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.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -41,80 +40,75 @@ import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelAccordion( - modifier: Modifier = Modifier, expanded: Boolean, onExpandedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, enabled: Boolean = true, showDivider: Boolean = false, header: @Composable (expanded: Boolean) -> Unit, trailingContent: @Composable (expanded: Boolean) -> Unit, content: @Composable () -> Unit, ) { - val rotation by animateFloatAsState( - targetValue = if (expanded) 180f else 0f, - label = "accordionChevronRotation", - ) + Column(modifier = modifier.background(Color.Transparent)) { + PrezelAccordionHeader( + enabled = enabled, + expanded = expanded, + onTap = { onExpandedChange(!expanded) }, + header = { header(expanded) }, + trailingContent = { trailingContent(expanded) }, + ) - Surface( - modifier = modifier, - color = Color.Transparent, - ) { - Column { - PrezelAccordionHeader( - enabled = enabled, - onTap = { onExpandedChange(!expanded) }, - header = { header(expanded) }, - trailingContent = { trailingContent(expanded) }, - icon = { PrezelAccordionChevron(rotation = rotation) }, - ) - - PrezelAccordionDivider(showDivider = showDivider) + PrezelAccordionDivider(showDivider = showDivider) - PrezelAccordionContent( - expanded = expanded, - content = content, - ) - } + PrezelAccordionContent( + expanded = expanded, + content = content, + ) } } @Composable private fun PrezelAccordionHeader( enabled: Boolean, + expanded: Boolean, onTap: () -> Unit, header: @Composable () -> Unit, trailingContent: @Composable () -> Unit, - icon: @Composable () -> Unit, ) { Row( modifier = Modifier .fillMaxWidth() + .padding(horizontal = PrezelTheme.spacing.V12) .defaultMinSize(minHeight = 48.dp) .clickable( enabled = enabled, indication = null, - interactionSource = remember { MutableInteractionSource() }, + interactionSource = null, onClick = onTap, ), verticalAlignment = Alignment.CenterVertically, ) { Box( modifier = Modifier.weight(1f), - ) { - header() - } + content = { header() }, + ) Spacer(Modifier.width(PrezelTheme.spacing.V12)) trailingContent() Spacer(Modifier.width(PrezelTheme.spacing.V8)) - icon() + PrezelAccordionChevron(expanded = expanded) } } @Composable -private fun PrezelAccordionChevron(rotation: Float) { +private fun PrezelAccordionChevron(expanded: Boolean) { + val rotation by animateFloatAsState( + targetValue = if (expanded) 180f else 0f, + label = "accordionChevronRotation", + ) + Icon( painter = painterResource(PrezelIcons.ChevronDown), contentDescription = stringResource(R.string.core_designsystem_accordion_desc), @@ -146,9 +140,7 @@ private fun PrezelAccordionContent( exit = fadeOut() + shrinkVertically(), ) { Column( - modifier = Modifier - .fillMaxWidth() - .padding(PrezelTheme.spacing.V12), + modifier = Modifier.fillMaxWidth(), ) { content() } @@ -201,7 +193,6 @@ private fun PrezelAccordionPreview_Expanded() { header = { Text( text = "Title", - modifier = Modifier.padding(start = 12.dp), style = PrezelTextStyles.Body2Medium.toTextStyle(), color = PrezelTheme.colors.textLarge, ) @@ -216,8 +207,9 @@ private fun PrezelAccordionPreview_Expanded() { ) { Text( text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", - style = PrezelTextStyles.Caption2Medium.toTextStyle(), + modifier = Modifier.padding(all = 12.dp), color = PrezelTheme.colors.textLarge, + style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) } } @@ -245,23 +237,22 @@ private fun PrezelAccordionPreview_Interactive() { onCheckedChange = {}, ) - Spacer(Modifier.width(4.dp)) - Text(text = "(필수) 이용약관") } }, trailingContent = { Text( text = "자세히 보기", - style = PrezelTextStyles.Caption2Medium.toTextStyle(), color = PrezelTheme.colors.textMedium, + style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) }, ) { Text( text = "클릭하면 열리고 닫힙니다.", - style = PrezelTextStyles.Caption2Medium.toTextStyle(), + modifier = Modifier.padding(all = 12.dp), color = PrezelTheme.colors.textLarge, + style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) } } From 17b9f0cdef68409b7aa2c3033d892ca83c27341a Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Fri, 27 Feb 2026 00:56:06 +0900 Subject: [PATCH 07/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EC=9C=A0=EC=97=B0?= =?UTF-8?q?=EC=84=B1=20=ED=99=95=EB=B3=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelAccordion` 컴포넌트의 내부 구조를 정리하고, 패딩 및 컴포저블 파라미터 설정을 유연하게 수정했습니다. * `header` 및 `trailingContent` 파라미터에서 불필요한 `expanded` 상태 전달 제거 * `contentPadding` 파라미터를 추가하여 헤더의 패딩을 외부에서 조절할 수 있도록 개선 * `PrezelAccordionDivider` 비공개 컴포저블을 제거하고 `PrezelHorizontalDivider`를 직접 사용하도록 로직 단순화 * `PrezelAccordionHeader`에 `contentPadding` 적용 및 관련 프리뷰 코드 업데이트 --- .../designsystem/component/PrezelAccordion.kt | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index dc3fa699..088f49ea 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.defaultMinSize @@ -45,20 +46,27 @@ fun PrezelAccordion( modifier: Modifier = Modifier, enabled: Boolean = true, showDivider: Boolean = false, - header: @Composable (expanded: Boolean) -> Unit, - trailingContent: @Composable (expanded: Boolean) -> Unit, + contentPadding: PaddingValues = PaddingValues(horizontal = PrezelTheme.spacing.V12), + header: @Composable () -> Unit, + trailingContent: @Composable () -> Unit, content: @Composable () -> Unit, ) { Column(modifier = modifier.background(Color.Transparent)) { PrezelAccordionHeader( enabled = enabled, expanded = expanded, + contentPadding = contentPadding, onTap = { onExpandedChange(!expanded) }, - header = { header(expanded) }, - trailingContent = { trailingContent(expanded) }, + header = { header() }, + trailingContent = { trailingContent() }, ) - PrezelAccordionDivider(showDivider = showDivider) + if (showDivider) { + PrezelHorizontalDivider( + type = PrezelDividerType.THICK, + color = PrezelTheme.colors.borderSmall, + ) + } PrezelAccordionContent( expanded = expanded, @@ -71,6 +79,7 @@ fun PrezelAccordion( private fun PrezelAccordionHeader( enabled: Boolean, expanded: Boolean, + contentPadding: PaddingValues, onTap: () -> Unit, header: @Composable () -> Unit, trailingContent: @Composable () -> Unit, @@ -78,7 +87,7 @@ private fun PrezelAccordionHeader( Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = PrezelTheme.spacing.V12) + .padding(contentPadding) .defaultMinSize(minHeight = 48.dp) .clickable( enabled = enabled, @@ -119,16 +128,6 @@ private fun PrezelAccordionChevron(expanded: Boolean) { ) } -@Composable -private fun PrezelAccordionDivider(showDivider: Boolean) { - if (!showDivider) return - - PrezelHorizontalDivider( - type = PrezelDividerType.THICK, - color = PrezelTheme.colors.borderSmall, - ) -} - @Composable private fun PrezelAccordionContent( expanded: Boolean, @@ -227,6 +226,7 @@ private fun PrezelAccordionPreview_Interactive() { expanded = expanded, onExpandedChange = { expanded = it }, showDivider = true, + contentPadding = PaddingValues(all = 0.dp), header = { Row( verticalAlignment = Alignment.CenterVertically, From 23456b8ac9141823de6318840fca95ff6baef443 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Wed, 11 Mar 2026 16:32:24 +0900 Subject: [PATCH 08/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20PrezelList=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelAccordion` 컴포넌트의 내부 구현을 `PrezelList` 기반으로 리팩토링하여 디자인 시스템 일관성을 높이고 가독성을 개선했습니다. * **PrezelAccordion 리팩토링**: * 내부 헤더 로직을 `PrezelList` 컴포넌트 사용으로 대체 * `title`, `size`, `nested`, `leadingContent` 파라미터 추가로 유연성 확장 * `animateContentSize`를 적용하여 상태 변화 시 부드러운 애니메이션 제공 * 불필요한 `PrezelAccordionHeader` 비공개 컴포저블 제거 * **PrezelCheckbox 수정**: * `Box`의 고정 크기(48.dp)를 제거하고 `modifier`를 통해 외부에서 제어하도록 수정 * 프리뷰 코드에서 `size(48.dp)` 명시적 지정 * **기타**: 프리뷰 예제 업데이트 및 관련 리소스 정리 --- .../designsystem/component/PrezelAccordion.kt | 226 +++++++----------- .../designsystem/component/PrezelCheckbox.kt | 28 ++- 2 files changed, 106 insertions(+), 148 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 088f49ea..5014fae3 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -1,6 +1,7 @@ package com.team.prezel.core.designsystem.component import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn @@ -10,14 +11,10 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth 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.Text import androidx.compose.runtime.Composable @@ -25,14 +22,14 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.team.prezel.core.designsystem.R +import com.team.prezel.core.designsystem.component.list.PrezelList +import com.team.prezel.core.designsystem.component.list.PrezelListSize import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.PreviewScaffold @@ -41,24 +38,40 @@ import com.team.prezel.core.designsystem.theme.PrezelTheme @Composable fun PrezelAccordion( + title: String, expanded: Boolean, onExpandedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, showDivider: Boolean = false, - contentPadding: PaddingValues = PaddingValues(horizontal = PrezelTheme.spacing.V12), - header: @Composable () -> Unit, - trailingContent: @Composable () -> Unit, - content: @Composable () -> Unit, + size: PrezelListSize = PrezelListSize.REGULAR, + nested: Boolean = false, + leadingContent: (@Composable RowScope.() -> Unit)? = null, + trailingContent: (@Composable RowScope.() -> Unit)? = null, + content: @Composable (() -> Unit)? = null, ) { - Column(modifier = modifier.background(Color.Transparent)) { - PrezelAccordionHeader( - enabled = enabled, - expanded = expanded, - contentPadding = contentPadding, - onTap = { onExpandedChange(!expanded) }, - header = { header() }, - trailingContent = { trailingContent() }, + Column( + modifier = modifier + .fillMaxWidth() + .animateContentSize(), + ) { + PrezelList( + title = title, + modifier = Modifier + .clickable( + enabled = enabled, + indication = null, + interactionSource = null, + ) { + onExpandedChange(!expanded) + }, + size = size, + nested = nested, + leadingContent = leadingContent, + trailingContent = { + trailingContent?.invoke(this) + PrezelAccordionChevron(expanded = expanded) + }, ) if (showDivider) { @@ -68,66 +81,15 @@ fun PrezelAccordion( ) } - PrezelAccordionContent( - expanded = expanded, - content = content, - ) - } -} - -@Composable -private fun PrezelAccordionHeader( - enabled: Boolean, - expanded: Boolean, - contentPadding: PaddingValues, - onTap: () -> Unit, - header: @Composable () -> Unit, - trailingContent: @Composable () -> Unit, -) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(contentPadding) - .defaultMinSize(minHeight = 48.dp) - .clickable( - enabled = enabled, - indication = null, - interactionSource = null, - onClick = onTap, - ), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier.weight(1f), - content = { header() }, - ) - Spacer(Modifier.width(PrezelTheme.spacing.V12)) - - trailingContent() - - Spacer(Modifier.width(PrezelTheme.spacing.V8)) - - PrezelAccordionChevron(expanded = expanded) + if (content != null) { + PrezelAccordionContent( + expanded = expanded, + content = content, + ) + } } } -@Composable -private fun PrezelAccordionChevron(expanded: Boolean) { - val rotation by animateFloatAsState( - targetValue = if (expanded) 180f else 0f, - label = "accordionChevronRotation", - ) - - Icon( - painter = painterResource(PrezelIcons.ChevronDown), - contentDescription = stringResource(R.string.core_designsystem_accordion_desc), - modifier = Modifier - .size(24.dp) - .rotate(rotation), - tint = PrezelTheme.colors.iconRegular, - ) -} - @Composable private fun PrezelAccordionContent( expanded: Boolean, @@ -152,30 +114,18 @@ private fun PrezelAccordionPreview_Collapsed() { PrezelTheme { PreviewScaffold { PrezelAccordion( + title = "Title", expanded = false, onExpandedChange = {}, showDivider = true, - header = { - Text( - text = "Title", - style = PrezelTextStyles.Body2Medium.toTextStyle(), - color = PrezelTheme.colors.textLarge, - ) - }, - trailingContent = { + content = { Text( - text = "Label", - style = PrezelTextStyles.Body2Bold.toTextStyle(), - color = PrezelTheme.colors.interactiveRegular, + text = "Content", + style = PrezelTextStyles.Body3Regular.toTextStyle(), + color = PrezelTheme.colors.textRegular, ) }, - ) { - Text( - text = "Content", - style = PrezelTextStyles.Body3Regular.toTextStyle(), - color = PrezelTheme.colors.textRegular, - ) - } + ) } } } @@ -186,59 +136,41 @@ private fun PrezelAccordionPreview_Expanded() { PrezelTheme { PreviewScaffold { PrezelAccordion( + title = "Title", expanded = true, onExpandedChange = {}, showDivider = true, - header = { + content = { Text( - text = "Title", - style = PrezelTextStyles.Body2Medium.toTextStyle(), + text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", + modifier = Modifier.padding(all = 12.dp), color = PrezelTheme.colors.textLarge, + style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) }, - trailingContent = { - Text( - text = "Label", - style = PrezelTextStyles.Body2Bold.toTextStyle(), - color = PrezelTheme.colors.interactiveRegular, - ) - }, - ) { - Text( - text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", - modifier = Modifier.padding(all = 12.dp), - color = PrezelTheme.colors.textLarge, - style = PrezelTextStyles.Caption2Medium.toTextStyle(), - ) - } + ) } } } @ThemePreview @Composable -private fun PrezelAccordionPreview_Interactive() { +private fun PrezelListAccordionPreview_Interactive() { PrezelTheme { var expanded by remember { mutableStateOf(false) } PreviewScaffold { PrezelAccordion( + title = "(필수) 이용약관", expanded = expanded, onExpandedChange = { expanded = it }, - showDivider = true, - contentPadding = PaddingValues(all = 0.dp), - header = { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - PrezelCheckbox( - checked = false, - size = CheckboxSize.REGULAR, - onCheckedChange = {}, - ) - - Text(text = "(필수) 이용약관") - } + showDivider = false, + leadingContent = { + PrezelCheckbox( + checked = false, + size = CheckboxSize.REGULAR, + onCheckedChange = {}, + ) }, trailingContent = { Text( @@ -247,14 +179,38 @@ private fun PrezelAccordionPreview_Interactive() { style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) }, - ) { - Text( - text = "클릭하면 열리고 닫힙니다.", - modifier = Modifier.padding(all = 12.dp), - color = PrezelTheme.colors.textLarge, - style = PrezelTextStyles.Caption2Medium.toTextStyle(), - ) - } + content = { + Box( + modifier = Modifier + .fillMaxWidth() + .background(PrezelTheme.colors.bgMedium) + .padding(all = 12.dp), + ) { + Text( + text = "본 약관은 서비스 이용과 관련한 기본적인 권리·의무 및 책임사항을 규정합니다.", + color = PrezelTheme.colors.textLarge, + style = PrezelTextStyles.Caption2Regular.toTextStyle(), + ) + } + }, + ) } } } + +@Composable +private fun PrezelAccordionChevron(expanded: Boolean) { + val rotation by animateFloatAsState( + targetValue = if (expanded) 180f else 0f, + label = "accordionChevronRotation", + ) + + Icon( + painter = painterResource(PrezelIcons.ChevronDown), + contentDescription = stringResource(R.string.core_designsystem_accordion_desc), + modifier = Modifier + .size(24.dp) + .rotate(rotation), + tint = PrezelTheme.colors.iconRegular, + ) +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt index ae84cd7f..7ebaa318 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt @@ -60,15 +60,13 @@ fun PrezelCheckbox( } Box( - modifier = modifier - .size(48.dp) - .toggleable( - value = checked, - interactionSource = null, - indication = null, - role = Role.Checkbox, - onValueChange = onCheckedChange, - ), + modifier = modifier.toggleable( + value = checked, + interactionSource = null, + indication = null, + role = Role.Checkbox, + onValueChange = onCheckedChange, + ), contentAlignment = Alignment.Center, ) { Icon( @@ -93,14 +91,16 @@ private fun PrezelRegularCheckboxPreview() { var checkState by remember { mutableStateOf(true) } PrezelCheckbox( - size = CheckboxSize.REGULAR, checked = checkState, + modifier = Modifier.size(48.dp), + size = CheckboxSize.REGULAR, onCheckedChange = { checkState = it }, ) PrezelCheckbox( - size = CheckboxSize.REGULAR, checked = !checkState, + modifier = Modifier.size(48.dp), + size = CheckboxSize.REGULAR, onCheckedChange = { checkState = it }, ) } @@ -121,14 +121,16 @@ private fun PrezelLargeCheckboxPreview() { var checkState by remember { mutableStateOf(true) } PrezelCheckbox( - size = CheckboxSize.LARGE, checked = checkState, + modifier = Modifier.size(48.dp), + size = CheckboxSize.LARGE, onCheckedChange = { checkState = it }, ) PrezelCheckbox( - size = CheckboxSize.LARGE, checked = !checkState, + modifier = Modifier.size(48.dp), + size = CheckboxSize.LARGE, onCheckedChange = { checkState = it }, ) } From aa6b563060db0783a4a96b5883dd97e16126910d Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Wed, 11 Mar 2026 16:40:14 +0900 Subject: [PATCH 09/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F?= =?UTF-8?q?=20=ED=94=84=EB=A6=AC=EB=B7=B0=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `PrezelAccordionChevron` 컴포넌트의 위치를 파일 내 상단으로 이동하여 가독성을 개선했습니다. - 개별적으로 분리되어 있던 아코디언 프리뷰(`Collapsed`, `Expanded`, `Interactive`)를 하나의 `PrezelAccordionPreview` 함수로 통합했습니다. - 프리뷰 내에서 `Arrangement.spacedBy`를 사용하여 컴포넌트 간 간격을 조정하고 가시성을 높였습니다. --- .../designsystem/component/PrezelAccordion.kt | 175 ++++++++---------- 1 file changed, 81 insertions(+), 94 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 5014fae3..9833c354 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -9,6 +9,7 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.RowScope @@ -90,6 +91,23 @@ fun PrezelAccordion( } } +@Composable +private fun PrezelAccordionChevron(expanded: Boolean) { + val rotation by animateFloatAsState( + targetValue = if (expanded) 180f else 0f, + label = "accordionChevronRotation", + ) + + Icon( + painter = painterResource(PrezelIcons.ChevronDown), + contentDescription = stringResource(R.string.core_designsystem_accordion_desc), + modifier = Modifier + .size(24.dp) + .rotate(rotation), + tint = PrezelTheme.colors.iconRegular, + ) +} + @Composable private fun PrezelAccordionContent( expanded: Boolean, @@ -110,107 +128,76 @@ private fun PrezelAccordionContent( @ThemePreview @Composable -private fun PrezelAccordionPreview_Collapsed() { - PrezelTheme { - PreviewScaffold { - PrezelAccordion( - title = "Title", - expanded = false, - onExpandedChange = {}, - showDivider = true, - content = { - Text( - text = "Content", - style = PrezelTextStyles.Body3Regular.toTextStyle(), - color = PrezelTheme.colors.textRegular, - ) - }, - ) - } - } -} - -@ThemePreview -@Composable -private fun PrezelAccordionPreview_Expanded() { - PrezelTheme { - PreviewScaffold { - PrezelAccordion( - title = "Title", - expanded = true, - onExpandedChange = {}, - showDivider = true, - content = { - Text( - text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", - modifier = Modifier.padding(all = 12.dp), - color = PrezelTheme.colors.textLarge, - style = PrezelTextStyles.Caption2Medium.toTextStyle(), - ) - }, - ) - } - } -} - -@ThemePreview -@Composable -private fun PrezelListAccordionPreview_Interactive() { +private fun PrezelAccordionPreview() { PrezelTheme { var expanded by remember { mutableStateOf(false) } PreviewScaffold { - PrezelAccordion( - title = "(필수) 이용약관", - expanded = expanded, - onExpandedChange = { expanded = it }, - showDivider = false, - leadingContent = { - PrezelCheckbox( - checked = false, - size = CheckboxSize.REGULAR, - onCheckedChange = {}, - ) - }, - trailingContent = { - Text( - text = "자세히 보기", - color = PrezelTheme.colors.textMedium, - style = PrezelTextStyles.Caption2Medium.toTextStyle(), - ) - }, - content = { - Box( - modifier = Modifier - .fillMaxWidth() - .background(PrezelTheme.colors.bgMedium) - .padding(all = 12.dp), - ) { + Column(verticalArrangement = Arrangement.spacedBy(40.dp)) { + PrezelAccordion( + title = "Collapsed Accordion", + expanded = false, + onExpandedChange = {}, + showDivider = true, + content = { Text( - text = "본 약관은 서비스 이용과 관련한 기본적인 권리·의무 및 책임사항을 규정합니다.", + text = "Content", + style = PrezelTextStyles.Body3Regular.toTextStyle(), + color = PrezelTheme.colors.textRegular, + ) + }, + ) + + PrezelAccordion( + title = "Expanded Accordion", + expanded = true, + onExpandedChange = {}, + showDivider = true, + content = { + Text( + text = "Content 영역입니다.\n여기에 설명이나 리스트가 들어갑니다.", + modifier = Modifier.padding(all = 12.dp), color = PrezelTheme.colors.textLarge, - style = PrezelTextStyles.Caption2Regular.toTextStyle(), + style = PrezelTextStyles.Caption2Medium.toTextStyle(), ) - } - }, - ) + }, + ) + + PrezelAccordion( + title = "(필수) 이용약관", + expanded = expanded, + onExpandedChange = { expanded = it }, + showDivider = false, + leadingContent = { + PrezelCheckbox( + checked = false, + size = CheckboxSize.REGULAR, + onCheckedChange = {}, + ) + }, + trailingContent = { + Text( + text = "자세히 보기", + color = PrezelTheme.colors.textMedium, + style = PrezelTextStyles.Caption2Medium.toTextStyle(), + ) + }, + content = { + Box( + modifier = Modifier + .fillMaxWidth() + .background(PrezelTheme.colors.bgMedium) + .padding(all = 12.dp), + ) { + Text( + text = "본 약관은 서비스 이용과 관련한 기본적인 권리·의무 및 책임사항을 규정합니다.", + color = PrezelTheme.colors.textLarge, + style = PrezelTextStyles.Caption2Regular.toTextStyle(), + ) + } + }, + ) + } } } } - -@Composable -private fun PrezelAccordionChevron(expanded: Boolean) { - val rotation by animateFloatAsState( - targetValue = if (expanded) 180f else 0f, - label = "accordionChevronRotation", - ) - - Icon( - painter = painterResource(PrezelIcons.ChevronDown), - contentDescription = stringResource(R.string.core_designsystem_accordion_desc), - modifier = Modifier - .size(24.dp) - .rotate(rotation), - tint = PrezelTheme.colors.iconRegular, - ) -} From 58799ba915171533b5855a84ce13405cc928e498 Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Thu, 12 Mar 2026 13:35:11 +0900 Subject: [PATCH 10/11] =?UTF-8?q?refactor:=20PrezelCheckbox,=20TopAppBar?= =?UTF-8?q?=20=EC=97=AC=EB=B0=B1=20=EC=A1=B0=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=ED=94=84=EB=A6=AC=EB=B7=B0=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelCheckbox` 컴포넌트의 내부 여백을 추가하고, 프리뷰 코드에서 사용되던 고정 크기 설정을 커스텀 보더 스타일로 변경하였습니다. * `PrezelCheckbox`의 `Box` 컨테이너에 `PrezelTheme.spacing.V8` 패딩 추가 * 프리뷰 내 `Modifier.size(48.dp)`를 `Modifier.drawDashBorder()`로 교체하여 시각적 구조 개선 * `drawDashBorder` 유틸리티 함수 임포트 추가 --- .../designsystem/component/PrezelCheckbox.kt | 25 +++++++++++-------- .../core/designsystem/component/TopAppBar.kt | 8 +++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt index 7ebaa318..926a7aba 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt @@ -27,6 +27,7 @@ import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.ThemePreview import com.team.prezel.core.designsystem.theme.PrezelTheme +import com.team.prezel.core.designsystem.util.drawDashBorder enum class CheckboxSize { REGULAR, @@ -60,13 +61,15 @@ fun PrezelCheckbox( } Box( - modifier = modifier.toggleable( - value = checked, - interactionSource = null, - indication = null, - role = Role.Checkbox, - onValueChange = onCheckedChange, - ), + modifier = modifier + .padding(all = PrezelTheme.spacing.V8) + .toggleable( + value = checked, + interactionSource = null, + indication = null, + role = Role.Checkbox, + onValueChange = onCheckedChange, + ), contentAlignment = Alignment.Center, ) { Icon( @@ -92,14 +95,14 @@ private fun PrezelRegularCheckboxPreview() { PrezelCheckbox( checked = checkState, - modifier = Modifier.size(48.dp), + modifier = Modifier.drawDashBorder(), size = CheckboxSize.REGULAR, onCheckedChange = { checkState = it }, ) PrezelCheckbox( checked = !checkState, - modifier = Modifier.size(48.dp), + modifier = Modifier.drawDashBorder(), size = CheckboxSize.REGULAR, onCheckedChange = { checkState = it }, ) @@ -122,14 +125,14 @@ private fun PrezelLargeCheckboxPreview() { PrezelCheckbox( checked = checkState, - modifier = Modifier.size(48.dp), + modifier = Modifier.drawDashBorder(), size = CheckboxSize.LARGE, onCheckedChange = { checkState = it }, ) PrezelCheckbox( checked = !checkState, - modifier = Modifier.size(48.dp), + modifier = Modifier.drawDashBorder(), size = CheckboxSize.LARGE, onCheckedChange = { checkState = it }, ) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt index b6f2658b..b21c07f3 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt @@ -102,7 +102,7 @@ private fun PrezelTopAppBarWithAllIconsPreview() { leadingIcon = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.ArrowLeft), + painter = painterResource(PrezelIcons.Blank), contentDescription = "뒤로가기", ) } @@ -110,13 +110,13 @@ private fun PrezelTopAppBarWithAllIconsPreview() { trailingIcons = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Search), + painter = painterResource(PrezelIcons.Blank), contentDescription = "검색", ) } IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.Menu), + painter = painterResource(PrezelIcons.Blank), contentDescription = "메뉴", ) } @@ -142,7 +142,7 @@ private fun PrezelTopAppBarScrollTestPreview() { leadingIcon = { IconButton(onClick = {}) { Icon( - painter = painterResource(PrezelIcons.ArrowLeft), + painter = painterResource(PrezelIcons.Blank), contentDescription = "뒤로가기", ) } From f67e78f09fa36998bacc52737aa2eb3c904e20df Mon Sep 17 00:00:00 2001 From: Ham BeomJoon Date: Thu, 12 Mar 2026 14:05:40 +0900 Subject: [PATCH 11/11] =?UTF-8?q?refactor:=20PrezelAccordion=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20PrezelList=20API?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrezelAccordion`의 상태 관리 방식을 내부 변수로 캡슐화하고, `PrezelList`의 슬롯 파라미터 타입을 변경하여 구조를 개선했습니다. * **PrezelAccordion**: * `expanded` 및 `onExpandedChange` 외부 주입 방식에서 `initiallyExpanded`를 사용한 내부 `rememberSaveable` 상태 관리 방식으로 변경 * `LocalMinimumInteractiveComponentSize`를 `Dp.Unspecified`로 설정하여 내부 리스트 아이템의 터치 영역 최적화 * `nested` 여부에 따라 `PrezelListSize`가 자동으로 결정되도록 로직 추가 * `content` 파라미터를 필수 값으로 변경하고 불필요한 null 체크 제거 * **PrezelList**: * `leadingContent` 및 `trailingContent`의 타입을 `@Composable (RowScope.() -> Unit)?`에서 `@Composable (() -> Unit)?`으로 변경하여 `RowScope` 의존성 제거 * **기타**: * `PrezelAccordion` 프리뷰 코드 내 체크박스와 하이퍼링크 버튼을 활용한 복합 예시 추가 및 디자인 확인을 위한 `drawDashBorder` 적용 (테스트용) * `PrezelHorizontalDivider` 호출 시 불필요한 기본 색상 파라미터 제거 --- .../designsystem/component/PrezelAccordion.kt | 96 ++++++++++--------- .../designsystem/component/list/PrezelList.kt | 8 +- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt index 9833c354..9f7f5dcb 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt @@ -12,23 +12,27 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon +import androidx.compose.material3.LocalMinimumInteractiveComponentSize import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.team.prezel.core.designsystem.R +import com.team.prezel.core.designsystem.component.button.PrezelHyperlinkButton import com.team.prezel.core.designsystem.component.list.PrezelList import com.team.prezel.core.designsystem.component.list.PrezelListSize import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles @@ -36,58 +40,57 @@ import com.team.prezel.core.designsystem.icon.PrezelIcons import com.team.prezel.core.designsystem.preview.PreviewScaffold import com.team.prezel.core.designsystem.preview.ThemePreview import com.team.prezel.core.designsystem.theme.PrezelTheme +import com.team.prezel.core.designsystem.util.drawDashBorder @Composable fun PrezelAccordion( title: String, - expanded: Boolean, - onExpandedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, - enabled: Boolean = true, - showDivider: Boolean = false, - size: PrezelListSize = PrezelListSize.REGULAR, + initiallyExpanded: Boolean = false, nested: Boolean = false, - leadingContent: (@Composable RowScope.() -> Unit)? = null, - trailingContent: (@Composable RowScope.() -> Unit)? = null, - content: @Composable (() -> Unit)? = null, + showDivider: Boolean = false, + leadingContent: @Composable (() -> Unit)? = null, + trailingContent: @Composable (() -> Unit)? = null, + content: @Composable (() -> Unit), ) { + var expanded by rememberSaveable { mutableStateOf(initiallyExpanded) } + Column( modifier = modifier .fillMaxWidth() .animateContentSize(), ) { - PrezelList( - title = title, - modifier = Modifier - .clickable( - enabled = enabled, - indication = null, - interactionSource = null, - ) { - onExpandedChange(!expanded) + CompositionLocalProvider( + LocalMinimumInteractiveComponentSize provides Dp.Unspecified, + ) { + PrezelList( + title = title, + modifier = Modifier + .clickable( + interactionSource = null, + indication = null, + onClick = { expanded = !expanded }, + ), + size = if (nested) PrezelListSize.SMALL else PrezelListSize.REGULAR, + nested = nested, + leadingContent = leadingContent, + trailingContent = { + trailingContent?.invoke() + PrezelAccordionChevron(expanded = expanded) }, - size = size, - nested = nested, - leadingContent = leadingContent, - trailingContent = { - trailingContent?.invoke(this) - PrezelAccordionChevron(expanded = expanded) - }, - ) + ) + } if (showDivider) { PrezelHorizontalDivider( type = PrezelDividerType.THICK, - color = PrezelTheme.colors.borderSmall, ) } - if (content != null) { - PrezelAccordionContent( - expanded = expanded, - content = content, - ) - } + PrezelAccordionContent( + expanded = expanded, + content = content, + ) } } @@ -130,14 +133,10 @@ private fun PrezelAccordionContent( @Composable private fun PrezelAccordionPreview() { PrezelTheme { - var expanded by remember { mutableStateOf(false) } - PreviewScaffold { Column(verticalArrangement = Arrangement.spacedBy(40.dp)) { PrezelAccordion( title = "Collapsed Accordion", - expanded = false, - onExpandedChange = {}, showDivider = true, content = { Text( @@ -150,8 +149,7 @@ private fun PrezelAccordionPreview() { PrezelAccordion( title = "Expanded Accordion", - expanded = true, - onExpandedChange = {}, + initiallyExpanded = true, showDivider = true, content = { Text( @@ -165,21 +163,25 @@ private fun PrezelAccordionPreview() { PrezelAccordion( title = "(필수) 이용약관", - expanded = expanded, - onExpandedChange = { expanded = it }, - showDivider = false, + modifier = Modifier + .padding(start = 24.dp) + .drawDashBorder(), + nested = true, leadingContent = { + var state by remember { mutableStateOf(false) } + PrezelCheckbox( - checked = false, + checked = state, + modifier = Modifier.drawDashBorder(), size = CheckboxSize.REGULAR, - onCheckedChange = {}, + onCheckedChange = { state = !state }, ) }, trailingContent = { - Text( + PrezelHyperlinkButton( text = "자세히 보기", - color = PrezelTheme.colors.textMedium, - style = PrezelTextStyles.Caption2Medium.toTextStyle(), + onClick = {}, + modifier = Modifier.drawDashBorder(), ) }, content = { diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt index 67184683..cf2ffc5f 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt @@ -31,8 +31,8 @@ fun PrezelList( modifier: Modifier = Modifier, size: PrezelListSize = PrezelListSize.REGULAR, nested: Boolean = false, - leadingContent: @Composable (RowScope.() -> Unit)? = null, - trailingContent: @Composable (RowScope.() -> Unit)? = null, + leadingContent: @Composable (() -> Unit)? = null, + trailingContent: @Composable (() -> Unit)? = null, ) { Row( modifier = modifier @@ -101,14 +101,14 @@ private fun PrezelListPreviewItem( showLeadingContent: Boolean, showTrailingContent: Boolean, ) { - val leadingContent: @Composable RowScope.() -> Unit = { + val leadingContent: @Composable () -> Unit = { Icon( painter = painterResource(id = PrezelIcons.Blank), contentDescription = "leading", ) } - val trailingContent: @Composable RowScope.() -> Unit = { + val trailingContent: @Composable () -> Unit = { Icon( painter = painterResource(id = PrezelIcons.Blank), contentDescription = "trailing",