PrezelDatePicker 구현#59
Conversation
새로운 디자인 시스템 컴포넌트로 DatePicker를 추가했습니다. * `DatePickerScreen`: 날짜 선택을 위한 전체 스크린 UI 구현 (TopAppBar, 요일 표시, 월별 리스트) * `MonthSection`, `MonthGrid`: 월별 날짜 그리드 레이아웃 구현 * `DayCellView`: 개별 날짜 셀의 디자인 및 상태(선택, 오늘, 일요일 등) 처리 * 날짜 계산 로직(`MonthGridBuilder`) 및 데이터 모델(`DatePickerModels`) 추가
디자인 시스템 내 날짜 선택을 위한 `PrezelDatePicker` 컴포넌트를 구현하고, 그리드 렌더링 로직 및 데이터 모델을 최적화했습니다.
* **feat: PrezelDatePicker 컴포넌트 추가**
* `LazyColumn`을 활용하여 여러 달을 리스트 형태로 보여주는 데이트 피커 구현
* 선택된 날짜 상태 관리(`selectedDate`) 및 '선택하기' 버튼 연동
* 닫기 버튼에 대한 접근성 서비스용 문자열 리소스(`core_designsystem_close_date_picker_desc`) 추가
* **refactor: DatePicker 모델 및 유이 모델 변환 로직 개선**
* `DayCellUiModel`에 `isInMonth` 프로퍼티 추가
* `toUiModel` 확장 함수에서 해당 월에 속하지 않는 날짜(이전/다음 달)는 비활성화(`enabled = false`)되도록 수정
* **refactor: MonthGrid 성능 최적화**
* `MonthGrid`에서 `buildMonthGrid`와 `lastWeekIndexToRender` 계산 로직을 하나의 `remember` 블록으로 결합하여 불필요한 재계산 방지
* **style: 변수명 및 리소스 참조 정리**
* 내부 상태 변수명을 `picked`에서 `selectedDate`로 변경하여 가독성 개선
* 하드코딩된 "닫기" 문자열을 리소스 ID 참조로 변경
`PrezelDatePicker` 컴포넌트의 내부 상태 관리 로직을 개선하여 상태를 외부에서 주입받도록 수정했습니다. * `selectedDate`를 관리하던 내부 `mutableStateOf`를 제거하고, `onSelect` 콜백을 통해 외부에서 상태를 직접 제어하도록 변경했습니다. * 가독성 향상을 위해 함수 파라미터의 순서를 조정했습니다. * 변경된 구조에 맞춰 Preview 코드를 수정했습니다.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughPrezel 디자인 시스템에 날짜 선택기 컴포넌트를 추가합니다. DayCellView, MonthGrid, MonthSection으로 구성되며, 최상위 공개 컴포넌트 PrezelDatePicker는 다중 월 레이아웃을 LazyColumn으로 표시합니다. 헤더(닫기 버튼 포함), 요일 표시 행, 월별 섹션, 선택 확인 푸터를 렌더링합니다. MonthGridBuilder 유틸리티는 6주 기반 달력 그리드를 생성하고, DayCell 데이터 클래스는 선택 상태와 표시 여부를 관리합니다. DatePickerStyle은 요일 색상 결정 로직을 제공합니다. 문자열 리소스와 kotlinx.datetime 의존성이 추가되었습니다. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGridBuilder.kt (1)
6-8:buildMonthGrid를internal로 변경하는 것을 권장합니다.이 함수는 날짜 선택기 내부 전용 구현 세부사항으로, 같은 패키지의
MonthGrid(internal)에서만 사용됩니다. 현재public으로 노출되어 있어 모듈 API 표면을 불필요하게 넓힙니다.♻️ 가시성 수정 제안
-fun buildMonthGrid( +internal fun buildMonthGrid( month: YearMonth, firstDayOfWeek: DayOfWeek, ): List<DayCell> {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGridBuilder.kt` around lines 6 - 8, 함수 buildMonthGrid가 퍼블릭으로 노출되어 있어 모듈 API를 불필요하게 넓히고 있으므로 해당 함수의 가시성을 internal로 변경하세요; 즉 MonthGrid와 같은 패키지 내부에서만 사용되도록 buildMonthGrid 선언(함수 이름: buildMonthGrid, 관련 타입: YearMonth, DayOfWeek)을 public에서 internal로 바꾸고, 이 함수를 호출하는 곳들이 같은 패키지 내에 있는지 확인해 필요 시 호출부를 같은 패키지로 옮기거나 접근 범위를 조정하세요.Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyles.kt (2)
6-6:@Composable어노테이션을 완전 한정 이름 대신 import로 선언하는 것을 권장합니다.같은 패키지의
DatePickerDayCellView.kt는import androidx.compose.runtime.Composable을 사용하며, 이 파일만 완전 한정 이름을 사용해 일관성이 떨어집니다.♻️ import 추가 제안
import androidx.compose.ui.graphics.Color +import androidx.compose.runtime.Composable import com.team.prezel.core.designsystem.theme.PrezelTheme -@androidx.compose.runtime.Composable +@Composable internal fun dayTextColor(ui: DayCellUiModel): Color =🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyles.kt` at line 6, Replace the fully-qualified annotation usage `@androidx.compose.runtime.Composable` in DatePickerStyles (the Composable annotation on the top of DatePickerStyles.kt) with an import-based annotation: add import androidx.compose.runtime.Composable at the top of the file and change the annotation to `@Composable` so it matches the style used in DatePickerDayCellView.kt and keeps annotations consistent across the design system.
7-13: 비활성화(disabled) 상태에 대한 색상 처리가 누락되어 있습니다.현재
dayTextColor는ui.enabled나ui.isInMonth를 확인하지 않습니다. 현재 구현에서는date == null인 셀이toUiModel에서null을 반환하므로 실제로 문제가 되지 않지만, 추후 최소/최대 날짜 제한 기능이 추가될 경우 비활성화된 인월(in-month) 날짜가 활성화된 날짜와 동일한 색상으로 렌더링됩니다.♻️ disabled 상태 색상 추가 제안
internal fun dayTextColor(ui: DayCellUiModel): Color = when { + !ui.enabled -> PrezelTheme.colors.textDisabled ui.isSelected -> PrezelTheme.colors.bgRegular ui.isToday -> PrezelTheme.colors.interactiveRegular ui.isSunday -> PrezelTheme.colors.accentMagentaRegular else -> PrezelTheme.colors.textMedium }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyles.kt` around lines 7 - 13, The dayTextColor function lacks handling for disabled/in-month state: update dayTextColor(ui: DayCellUiModel) to first check ui.enabled and ui.isInMonth and return the theme's disabled text color when the cell is not enabled or not in the current month (e.g., PrezelTheme.colors.textDisabled or an equivalent low-emphasis color) before the existing ui.isSelected/ui.isToday/ui.isSunday branches so disabled in-month dates render with the disabled color.Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerModels.kt (1)
6-19:DayCell과DayCellUiModel을internal로 변경하는 것을 권장합니다.두 클래스는
datepicker패키지 내부에서만 소비되며 모듈 공개 API의 일부가 아닙니다. 현재public으로 선언되어 있어 설계 시스템 모듈을 사용하는 소비자에게 의도치 않게 노출됩니다.♻️ 가시성 수정 제안
-data class DayCell( +internal data class DayCell( val date: LocalDate?, val isInMonth: Boolean, ) -data class DayCellUiModel( +internal data class DayCellUiModel( val date: LocalDate, val text: String, val isSelected: Boolean, val isToday: Boolean, val isSunday: Boolean, val isInMonth: Boolean, val enabled: Boolean, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerModels.kt` around lines 6 - 19, The DayCell and DayCellUiModel data classes are unnecessarily public; change their visibility to internal by updating the declarations of DayCell and DayCellUiModel to internal data class so they are only visible inside the datepicker package; update any external usages inside the module if necessary and run a compile to catch and fix any places that relied on the public visibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt`:
- Line 96: Move the hardcoded Korean label by adding a new string resource
(e.g., add <string name="core_designsystem_select">선택하기</string> to strings.xml)
and update PrezelDatePicker.kt to use that resource instead of the literal
(replace text = "선택하기" with text =
stringResource(R.string.core_designsystem_select) or
context.getString(R.string.core_designsystem_select) as appropriate); ensure you
import androidx.compose.ui.res.stringResource if using Compose.
- Around line 44-110: PrezelDatePicker is too long and violates Detekt
LongMethod; extract the header (TopAppBar + WeekdayRow +
PrezelHorizontalDivider) and footer (PrezelHorizontalDivider + PrezelTextButton)
into two private composable helpers (e.g., private fun
PrezelDatePickerHeader(...) and private fun PrezelDatePickerFooter(...)) and
replace the inline header/footer blocks inside PrezelDatePicker with calls to
those helpers, passing only the needed params (title, onClose for header;
selectedDate, onConfirm for footer) while keeping the LazyColumn/MonthSection
usage intact.
---
Nitpick comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerModels.kt`:
- Around line 6-19: The DayCell and DayCellUiModel data classes are
unnecessarily public; change their visibility to internal by updating the
declarations of DayCell and DayCellUiModel to internal data class so they are
only visible inside the datepicker package; update any external usages inside
the module if necessary and run a compile to catch and fix any places that
relied on the public visibility.
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyles.kt`:
- Line 6: Replace the fully-qualified annotation usage
`@androidx.compose.runtime.Composable` in DatePickerStyles (the Composable
annotation on the top of DatePickerStyles.kt) with an import-based annotation:
add import androidx.compose.runtime.Composable at the top of the file and change
the annotation to `@Composable` so it matches the style used in
DatePickerDayCellView.kt and keeps annotations consistent across the design
system.
- Around line 7-13: The dayTextColor function lacks handling for
disabled/in-month state: update dayTextColor(ui: DayCellUiModel) to first check
ui.enabled and ui.isInMonth and return the theme's disabled text color when the
cell is not enabled or not in the current month (e.g.,
PrezelTheme.colors.textDisabled or an equivalent low-emphasis color) before the
existing ui.isSelected/ui.isToday/ui.isSunday branches so disabled in-month
dates render with the disabled color.
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGridBuilder.kt`:
- Around line 6-8: 함수 buildMonthGrid가 퍼블릭으로 노출되어 있어 모듈 API를 불필요하게 넓히고 있으므로 해당
함수의 가시성을 internal로 변경하세요; 즉 MonthGrid와 같은 패키지 내부에서만 사용되도록 buildMonthGrid 선언(함수
이름: buildMonthGrid, 관련 타입: YearMonth, DayOfWeek)을 public에서 internal로 바꾸고, 이 함수를
호출하는 곳들이 같은 패키지 내에 있는지 확인해 필요 시 호출부를 같은 패키지로 옮기거나 접근 범위를 조정하세요.
`PrezelDatePicker`의 가독성과 유지보수성을 높이기 위해 내부 UI 로직을 분리하고 하드코딩된 문자열을 리소스화했습니다.
* `DatePickerHeader`, `DatePickerFooter` 컴포저블을 추출하여 `PrezelDatePicker` 구조를 단순화했습니다.
* 하단 확인 버튼의 텍스트("선택하기")를 `core_designsystem_date_picker_confirm_btn` 리소스로 대체했습니다.
* `DatePickerStyles.kt` 내 불필요한 full qualifier `androidx.compose.runtime.Composable`을 `import` 문으로 정리했습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt (2)
131-152:WeekdayRow요일 레이블이 하드코딩되어 있음
"일", "월", "화", "수", "목", "금", "토"7개 레이블이 컴포저블 내부에 직접 리스트로 정의되어 있습니다. 프로젝트의 나머지 UI 문자열은 모두strings.xml로 외부화되어 있으므로, 일관성 및 향후 현지화를 고려하면 이 레이블도string-array리소스로 이동하는 것을 권장합니다.♻️ 리팩터링 제안
strings.xml에 추가:+ <string-array name="core_designsystem_weekday_labels"> + <item>일</item> + <item>월</item> + <item>화</item> + <item>수</item> + <item>목</item> + <item>금</item> + <item>토</item> + </string-array>
WeekdayRow수정:`@Composable` private fun WeekdayRow() { - val labels = listOf("일", "월", "화", "수", "목", "금", "토") + val labels = stringArrayResource(R.array.core_designsystem_weekday_labels).toList() ... }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt` around lines 131 - 152, WeekdayRow currently hardcodes the weekday labels ("일","월",...) inside the composable; extract these into a string-array resource (e.g., <string-array name="weekday_labels"> in strings.xml) and update WeekdayRow to load them via stringArrayResource(R.array.weekday_labels) (ensure you import androidx.compose.ui.res.stringArrayResource) and use the resulting array/list in the existing labels.forEach block so the UI follows the project's resource/localization pattern.
106-106:DatePickerFooter에서 불필요한@OptIn(ExperimentalMaterial3Api::class)제거
DatePickerFooter는PrezelHorizontalDivider와PrezelTextButton만 호출하는데, 두 컴포저블 모두@OptIn어노테이션이 필요하지 않습니다. 반면DatePickerHeader는PrezelTopAppBar를 호출하므로@OptIn이 필요합니다. 불필요한 어노테이션을 제거해 코드를 정리하세요.수정 제안
-@OptIn(ExperimentalMaterial3Api::class) `@Composable` private fun DatePickerFooter(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt` at line 106, DatePickerFooter에 붙어 있는 불필요한 `@OptIn`(ExperimentalMaterial3Api::class) 어노테이션을 제거하세요; DatePickerFooter는 PrezelHorizontalDivider와 PrezelTextButton만 호출하므로 해당 OptIn이 필요 없습니다. 반면 DatePickerHeader는 PrezelTopAppBar를 사용하므로 `@OptIn`(ExperimentalMaterial3Api::class)는 DatePickerHeader에만 유지하도록 정리하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Prezel/core/designsystem/src/main/res/values/strings.xml`:
- Line 4: 문자열 리소스 core_designsystem_close_date_picker_desc가 영어 혼용("DatePicker
닫기")으로 되어 있어 접근성 읽기가 부자연스럽습니다; core_designsystem_close_date_picker_desc 값을 "날짜
선택기 닫기"처럼 완전한 한국어 표현으로 변경하여 core_designsystem_close_floating_btn_content_desc 등
기존 한국어 표기와 일관되게 수정하고, 변경 후 TalkBack/스크린리더에서 의도한 대로 읽히는지 확인하세요.
---
Nitpick comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt`:
- Around line 131-152: WeekdayRow currently hardcodes the weekday labels
("일","월",...) inside the composable; extract these into a string-array resource
(e.g., <string-array name="weekday_labels"> in strings.xml) and update
WeekdayRow to load them via stringArrayResource(R.array.weekday_labels) (ensure
you import androidx.compose.ui.res.stringArrayResource) and use the resulting
array/list in the existing labels.forEach block so the UI follows the project's
resource/localization pattern.
- Line 106: DatePickerFooter에 붙어 있는 불필요한 `@OptIn`(ExperimentalMaterial3Api::class)
어노테이션을 제거하세요; DatePickerFooter는 PrezelHorizontalDivider와 PrezelTextButton만 호출하므로
해당 OptIn이 필요 없습니다. 반면 DatePickerHeader는 PrezelTopAppBar를 사용하므로
`@OptIn`(ExperimentalMaterial3Api::class)는 DatePickerHeader에만 유지하도록 정리하세요.
디자인 시스템에 `PrezelDatePicker` 컴포넌트를 추가하고 관련 스타일과 로직을 개선했습니다.
* `PrezelDatePicker` 컴포넌트 추가
* 헤더, 요일 표시, 월별 그리드, 푸터(확인 버튼)로 구성된 날짜 선택 다이얼로그를 구현했습니다.
* `DatePickerState`를 통해 현재 연도/월, 선택된 날짜, 달력 표시 여부 등의 상태를 관리합니다.
* 스타일 및 리소스 추가
* 선택된 날짜, 오늘, 비활성화된 날짜 등에 따라 텍스트 색상을 다르게 적용하는 `dayTextColor` 로직을 추가했습니다.
* 요일 라벨(`일`~`토`)을 `string-array` 리소스로 분리하여 관리하도록 개선했습니다.
* 접근성 수정 및 내부 구현 변경
* `DatePicker` 관련 모델(`DayCell`, `DayCellUiModel`)과 유틸리티 함수(`buildMonthGrid`)의 접근 제어자를 `internal`로 변경했습니다.
* DatePicker 닫기 버튼의 콘텐츠 설명을 "DatePicker 닫기"에서 "날짜 선택 닫기"로 명확하게 수정했습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyles.kt`:
- Line 11: The selected date cell is using bgRegular for its text color (in the
DatePickerStyles mapping for ui.isSelected) which yields poor contrast in dark
mode; update the mapping in DatePickerStyles so that when ui.isSelected the text
color uses a dedicated text token (e.g., textRegular or textMedium) or an
explicit high-contrast color (such as white) instead of
PrezelTheme.colors.bgRegular, and ensure the selected cell background remains
interactiveRegular; additionally, add an isSaturday Boolean to the
DayCellUiModel (matching the existing isSunday) so you can apply distinct
styling for Saturdays per Korean calendar conventions and update any code that
constructs/uses DayCellUiModel accordingly.
---
Duplicate comments:
In `@Prezel/core/designsystem/src/main/res/values/strings.xml`:
- Line 4: The accessibility string core_designsystem_close_date_picker_desc
currently reads "날짜 선택 닫기" which may be ambiguous for TalkBack; update its value
to "날짜 선택기 닫기" to clearly identify the component being closed—locate the string
resource named core_designsystem_close_date_picker_desc in strings.xml and
replace the text accordingly so TalkBack announces the component name
unambiguously.
|
|
||
| internal data class DayCell( | ||
| val date: LocalDate?, | ||
| val isInMonth: Boolean, |
There was a problem hiding this comment.
isInMonth는 날짜 그 자체의 속성이 아니라 “이 날짜가 지금 우리가 그리는 달의 소속인가?”를 나타내는 컨텍스트 값입니다.
없으면 MonthGrid등의 class안에서 일일이 비교하며 그려야 해서 따로 뺐습니다.
변수명을 isCurrentMonth으로 바꿀까요?
There was a problem hiding this comment.
val isVisible = isInMonth && !isPastisVisible은 현재 이 지점에서만 사용되고 있는 것 같아요.
또한 UiModel에 이미 date: LocalDate가 존재하기 때문에, 내부에서 충분히 계산 가능한 파생 상태로 보입니다.
이런 관점에서 보면 isVisible을 DayCell 외부에서 계산해 전달했을 때 얻는 이점이 무엇인지가 조금 명확하지 않은 것 같아요.
다만 전체 로직을 아직 다 확인한 것은 아니기 때문에, 다시 한 번 확인해보고 외부에서 주입해야 할 명확한 이유가 있다면 유지하는 방향도 괜찮을 것 같습니다.
| import com.team.prezel.core.designsystem.theme.PrezelTheme | ||
|
|
||
| @Composable | ||
| internal fun dayTextColor(ui: DayCellUiModel): Color = |
There was a problem hiding this comment.
| internal fun dayTextColor(ui: DayCellUiModel): Color = | |
| internal fun DayCellUiModel.dayTextColor(): Color = |
There was a problem hiding this comment.
보통 확장함수로 표현하는 것이 좋다 생각하나요?? 어떤 기준으로 일반함수와 확장함수 정의를 차이를 두는지 궁금합니다.
| val isToday: Boolean, | ||
| val isSunday: Boolean, | ||
| val isInMonth: Boolean, | ||
| val enabled: Boolean, |
There was a problem hiding this comment.
일단 지난날짜를 안보이게 하긴했는데, 정책이 지난날짜가 안보이는게 맞는거겠죠..?
| initialMonth: YearMonth, | ||
| today: LocalDate, |
There was a problem hiding this comment.
initialMonth와 today를 모두 전달할 필요는 없어 보입니다.
지난 날짜는 노출되지 않는 요구사항이 있으므로, 과거로 이동하지 않는다고 가정하면 initialMonth는 항상 today의 월로 결정됩니다.
따라서 initialMonth는 내부에서 today를 기준으로 계산하고, today에는 기본값을 제공하는 방향이 더 적절해 보입니다.
DatePicker 관련 모델 및 스타일 파일명을 단수형으로 변경하고, 매직 넘버로 선언된 여백 값을 디자인 시스템의 `PrezelTheme.spacing`으로 교체하였습니다. * `DatePickerModels.kt` -> `DatePickerModel.kt`로 변경 및 `DayCellUiModel`에 `@Immutable` 어노테이션 추가 * `DatePickerStyles.kt` -> `DatePickerStyle.kt`로 변경 * `MonthSection`, `PrezelDatePicker`, `MonthGrid` 내 `dp` 단위 여백을 `PrezelTheme.spacing` 상수로 수정 * `DatePickerDayCellView` 클릭 시 리플 효과(`ripple()`) 추가 및 인터렉션 로직 개선
DatePicker 구성 요소의 가독성과 코드 구조를 개선했습니다. * `DatePickerModel.kt`: `date` 변수의 널 체크 로직을 정리하고 불필요한 지역 변수 할당을 제거했습니다. * `DatePickerStyle.kt`: 기존 `dayTextColor` 함수를 `DayCellUiModel`의 확장 함수로 변경하여 캡슐화를 강화했습니다. * `DatePickerDayCellView.kt`: 확장 함수로 변경된 `dayTextColor`를 적용하고 코드 포맷을 정리했습니다.
DatePicker 구성 요소의 디자인 일관성을 높이고 가독성을 개선했습니다. * `DatePickerDayCellView`: 날짜 셀의 패딩 값을 하드코딩된 `6.dp`에서 `PrezelTheme.spacing.V4`로 변경했습니다. * `MonthGrid`: 컴포넌트 확인을 위한 `MonthGridPreview`를 추가했습니다. * `MonthSection`: 컴포넌트 확인을 위한 `MonthSectionPreview`를 추가했습니다.
PrezelDatePicker 컴포넌트에서 오늘 이전의 날짜를 숨기고 선택할 수 없도록 개선하였습니다. * `DayCellUiModel` 및 `toUiModel`: `isVisible` 상태를 추가하고, 현재 월(isInMonth)에 해당하면서 오늘 이후인 날짜만 노출 및 활성화되도록 로직 수정 * `PrezelDatePicker`: `initialMonth`와 `today` 파라미터의 기본값을 설정하여 사용성을 높이고, 내부 `LazyColumn`의 여백을 디자인 시스템 토큰(`PrezelTheme.spacing.V16`)으로 교체 * `DatePickerDayCellView`: `uiModel.isVisible`이 `false`인 경우 날짜 텍스트를 렌더링하지 않도록 수정 및 코드 정렬 적용
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyle.kt (1)
7-15: LGTM — 우선순위 로직 정상우선순위(비활성 > 선택됨 > 오늘 > 일요일 > 기본)가 올바르게 구현되어 있습니다.
선택 상태 텍스트 색상으로
bgRegular를 사용하는 것은 선택 셀 배경(원형 인디케이터)에 대비되는 텍스트 색상을 의도한 것으로 보이나,bg접두사는 배경 토큰을 연상시켜 의미가 불명확합니다. 인라인 주석 한 줄(// selection indicator 내 텍스트 색상)을 추가하면 다른 개발자의 혼란을 줄일 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyle.kt` around lines 7 - 15, The priority logic in DayCellUiModel.dayTextColor() is correct but the use of PrezelTheme.colors.bgRegular for the selected-state text can be confusing because the "bg" prefix implies a background token; add a one-line inline comment above the this.isSelected branch (in DayCellUiModel.dayTextColor) stating something like "// text color for selection indicator (contrasts with selected cell background)" to clarify intent for future readers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerModel.kt`:
- Around line 31-42: 현재 DatePickerModel의 DayCellUiModel 생성에서 isSelected = date
== selectedDate가 isVisible·enabled를 무시해, 과거(비표시/비활성) 날짜가 selectedDate로 넘어오면 확인
버튼이 활성화됩니다; 수정 방법은 DayCellUiModel에 전달할 isSelected 계산에 isVisible 및 enabled 상태를
포함하여(isSelected가 true인 경우에만 실제로 셀을 보이고 활성화된 상태와 일치하게) 설정하고(참고: DatePickerModel의
isVisible 변수와 enabled 파라미터, DayCellUiModel 생성 지점), 추가로 DatePickerFooter에서
enabled = selectedDate != null 로만 판단하지 말고 선택된 날짜가 현재 보이거나 활성화된 날짜인지 재검증하도록 보호
검사를 추가하십시오(참고: DatePickerFooter 호출부와 DatePickerModel의 selectedDate 처리 로직).
---
Duplicate comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt`:
- Around line 44-127: All requested review issues have been addressed so no code
changes are required; confirm and merge the PR. Specifically, ensure the
extracted private composables DatePickerHeader, DatePickerFooter, and WeekdayRow
remain private and used by PrezelDatePicker, and that the hardcoded confirm
string was replaced with
stringResource(R.string.core_designsystem_date_picker_confirm_btn) before
approving.
---
Nitpick comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyle.kt`:
- Around line 7-15: The priority logic in DayCellUiModel.dayTextColor() is
correct but the use of PrezelTheme.colors.bgRegular for the selected-state text
can be confusing because the "bg" prefix implies a background token; add a
one-line inline comment above the this.isSelected branch (in
DayCellUiModel.dayTextColor) stating something like "// text color for selection
indicator (contrasts with selected cell background)" to clarify intent for
future readers.
| val isToday: Boolean, | ||
| val isSunday: Boolean, | ||
| val isInMonth: Boolean, | ||
| val enabled: Boolean, |
|
|
||
| internal data class DayCell( | ||
| val date: LocalDate?, | ||
| val isInMonth: Boolean, |
There was a problem hiding this comment.
val isVisible = isInMonth && !isPastisVisible은 현재 이 지점에서만 사용되고 있는 것 같아요.
또한 UiModel에 이미 date: LocalDate가 존재하기 때문에, 내부에서 충분히 계산 가능한 파생 상태로 보입니다.
이런 관점에서 보면 isVisible을 DayCell 외부에서 계산해 전달했을 때 얻는 이점이 무엇인지가 조금 명확하지 않은 것 같아요.
다만 전체 로직을 아직 다 확인한 것은 아니기 때문에, 다시 한 번 확인해보고 외부에서 주입해야 할 명확한 이유가 있다면 유지하는 방향도 괜찮을 것 같습니다.
| import com.team.prezel.core.designsystem.theme.PrezelTheme | ||
|
|
||
| @Composable | ||
| internal fun DayCellUiModel.dayTextColor(): Color = |
There was a problem hiding this comment.
보통 확장함수로 표현하는 것이 좋다 생각하나요?? 어떤 기준으로 일반함수와 확장함수 정의를 차이를 두는지 궁금합니다.
항상 확장함수가 좋다고 생각하지 않습니다.
이 로직이 특정 타입의 변환·표현처럼 해당 타입의 책임으로 자연스럽게 읽히고,
외부 상태나 정책 판단 없이 receiver의 정보만으로 동작한다면 확장 함수,
반대로 여러 조건·맥락을 고려한 결정 로직이거나 타입의 책임을 넘는다면 일반 함수로 두는 게 적절해 보입니다.
`DatePicker` 컴포넌트에서 사용되는 `DayCellUiModel`의 프로퍼티를 정리하고 관련 로직을 수정했습니다. * `DayCellUiModel`에서 불필요한 `date` 필드를 제거하고, `text`를 `dayText`로 변경하였습니다. * `DatePickerDayCellView`에서 변경된 `dayText` 필드를 사용하도록 수정하고, `Box` 컴포저블의 수정자(Modifier) 체이닝 가독성을 개선했습니다.
* feat: `PrezelDatePicker` 내 닫기 버튼 추가 및 레이아웃 수정
* `DatePickerFooter`에 `onClose` 콜백을 추가하고, 기존 `PrezelTextButton`을 `PrezelButtonArea`로 교체하여 확인/닫기 버튼이 공존하는 구조로 개선했습니다.
* `PrezelButtonArea` 적용을 통해 버튼 영역의 배경 및 상단 구분선 스타일을 업데이트했습니다.
* feat: 관련 문자열 리소스 추가
* `core_designsystem_date_picker_close_btn` ("닫기") 리소스를 추가했습니다.
`PrezelDatePicker`의 내부 데이터 모델과 렌더링 로직을 최적화하고, UI 구성을 일부 변경하였습니다.
* **데이터 모델 및 그리드 생성 로직 개선**:
* `DayCellUiModel`을 제거하고 `DayCell` 클래스로 통합하여 상태 관리를 단순화했습니다.
* `buildMonthGrid`가 `LocalDate?` 리스트를 반환하도록 수정하고, `kotlinx-collections-immutable`을 적용하여 안정성을 높였습니다.
* `DayCell`에서 `isSunday`, `dayText` 등을 직접 계산하도록 변경했습니다.
* **UI 컴포넌트 리팩터링**:
* `MonthGrid` 내부의 주간 반복 로직을 `WeekRow` 컴포저블로 분리했습니다.
* `DayCellView`에서 사용되지 않는 `enabled` 상태를 제거하고 `isVisible` 기반의 클릭 처리를 적용했습니다.
* 일요일 텍스트 색상 및 선택 상태 등에 따른 색상 적용 로직을 정리했습니다.
* **기능 및 스타일 수정**:
* `PrezelDatePicker`의 `LazyColumn`에 `overscrollEffect = null`을 추가하여 스크롤 효과를 제거했습니다.
* `DatePickerFooter`에서 닫기 버튼(subButton)을 제거하고, 날짜가 선택되었을 때만 확인 버튼이 활성화되도록 수정했습니다.
* 프리뷰 데이터의 `today` 날짜를 최신화했습니다.
DatePicker 관련 컴포넌트에서 사용하던 `java.time` API를 멀티플랫폼 호환성을 위해 `kotlinx-datetime`으로 전면 교체하였습니다. * `PrezelDatePicker`, `MonthGrid`, `MonthSection` 등 주요 컴포넌트의 날짜 관련 타입을 `kotlinx.datetime.LocalDate`, `kotlinx.datetime.YearMonth` 등으로 변경했습니다. * 날짜 계산 및 비교 로직을 `kotlinx-datetime`의 API에 맞게 수정했습니다. (`plusMonths` -> `plus(DateTimeUnit.MONTH)`, `atDay` -> `onDay` 등) * `kotlinx-datetime` 라이브러리 의존성을 `core:designsystem` 모듈에 추가하고, `libs.versions.toml`에 관련 버전을 정의했습니다. * `PrezelDatePicker` 컴포넌트의 불필요한 `ExperimentalMaterial3Api` 어노테이션을 제거했습니다.
DatePicker 관련 컴포넌트의 역할을 더 명확하게 나타내기 위해 `DatePickerModel.kt` 파일의 이름을 `DayCell.kt`로 변경했습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGrid.kt (1)
55-61: 과거 날짜가 공백으로 렌더링됩니다.
isVisible = !isPast로 인해 과거 날짜가 텍스트 없이 빈 칸으로 보여 캘린더 인지가 떨어질 수 있습니다. 과거 날짜 “비노출”이 요구사항이 아니라면, 텍스트는 표시하되 비활성 스타일/클릭 비활성으로 처리하는 방향을 검토해 주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGrid.kt` around lines 55 - 61, The MonthGrid DayCell currently hides past dates by setting isVisible = !isPast; instead, keep past dates visible but styled/disabled: change the DayCell construction in MonthGrid (where uiModel is created) to set isVisible = true and add or set a disabled/interactive flag (e.g., isDisabled = isPast or isClickable = !isPast) so the text renders for past dates while preventing interaction and applying disabled styling, and update any rendering logic that relies on isVisible to use the new disabled flag for appearance and click handling.Prezel/gradle/libs.versions.toml (1)
22-26: 버전 키 이름 오타 수정 필요
kotlintxCollectionsImmutable을kotlinxCollectionsImmutable로 변경하여 다른 kotlinx 라이브러리 버전 키의 명명 규칙과 일치시키세요.♻️ 수정안
-kotlintxCollectionsImmutable = "0.4.0" +kotlinxCollectionsImmutable = "0.4.0"-kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlintxCollectionsImmutable" } +kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinxCollectionsImmutable" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Prezel/gradle/libs.versions.toml` around lines 22 - 26, 파일의 버전 키 이름이 오타입니다: 변경해야 할 심볼은 kotlintxCollectionsImmutable이며 이를 kotlinxCollectionsImmutable로 수정하세요; libs.versions.toml에서 kotlintxCollectionsImmutable 항목 이름을 kotlinxCollectionsImmutable로 바꾸고, 프로젝트에서 이 버전 키를 참조하는 모든 사용처(예: 버전 카탈로그 참조나 build.gradle(.kts) 내 참조 문자열)를 동일한 새 키명으로 업데이트하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthSection.kt`:
- Around line 24-28: Add a string resource named
core_designsystem_datepicker_month_title (e.g. "%1$d년 %2$d월") and replace the
hardcoded title in the Text composable with a localized stringResource call: use
stringResource(R.string.core_designsystem_datepicker_month_title,
yearMonth.year, yearMonth.month.number) so the Text (inside MonthSection) uses
the resource instead of the literal; keep the existing color and style
(PrezelTheme.colors.textLarge / PrezelTheme.typography.body3Medium).
---
Nitpick comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGrid.kt`:
- Around line 55-61: The MonthGrid DayCell currently hides past dates by setting
isVisible = !isPast; instead, keep past dates visible but styled/disabled:
change the DayCell construction in MonthGrid (where uiModel is created) to set
isVisible = true and add or set a disabled/interactive flag (e.g., isDisabled =
isPast or isClickable = !isPast) so the text renders for past dates while
preventing interaction and applying disabled styling, and update any rendering
logic that relies on isVisible to use the new disabled flag for appearance and
click handling.
In `@Prezel/gradle/libs.versions.toml`:
- Around line 22-26: 파일의 버전 키 이름이 오타입니다: 변경해야 할 심볼은
kotlintxCollectionsImmutable이며 이를 kotlinxCollectionsImmutable로 수정하세요;
libs.versions.toml에서 kotlintxCollectionsImmutable 항목 이름을
kotlinxCollectionsImmutable로 바꾸고, 프로젝트에서 이 버전 키를 참조하는 모든 사용처(예: 버전 카탈로그 참조나
build.gradle(.kts) 내 참조 문자열)를 동일한 새 키명으로 업데이트하세요.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
Prezel/core/designsystem/build.gradle.ktsPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerDayCellView.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DatePickerStyle.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/DayCell.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGrid.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGridBuilder.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthSection.ktPrezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.ktPrezel/gradle/libs.versions.toml
🚧 Files skipped from review as they are similar to previous changes (2)
- Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/MonthGridBuilder.kt
- Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/datepicker/PrezelDatePicker.kt
DatePicker의 월(Month) 표시 부분에 하드코딩된 문자열 대신, `%1$d년 %2$d월` 형식의 문자열 리소스를 사용하도록 수정했습니다.



📌 작업 내용
🧩 관련 이슈
📸 스크린샷
2026-02-20.13.36.28.mov
📢 논의하고 싶은 내용
Summary by CodeRabbit
릴리스 노트