Skip to content

Conversation

@moondev03
Copy link
Member

@moondev03 moondev03 commented Jan 23, 2026

📌 작업 내용

  • Modifier.dropShadowCache() 구현
  • PrezelFloatingButton 구현
  • PrezelFloatingMenuButton, PrezelFloatingButtonMenu, PrezelFloatingButtomMenuItem 구현

PrezelFloatingButtonStyle은 하위 컴포넌트인 PrezelFloatingButtonMenuItem의 디자인을 결정하는 역할을 합니다.

PrezelFloatingButtonMenu에서는 CompositionLocalProvider를 통해 현재 PrezelFloatingButtonStyle에 매핑된 PrezelFloatingButtonMenuItemStyle을 하위 컴포넌트로 전달하며, PrezelFloatingButtonMenuItem은 상위에서 제공된 스타일을 기준으로 자신의 UI를 구성합니다.


🧩 관련 이슈


📸 스크린샷

image

비고

PrezelFloatingButton 예시 코드

메뉴 기능이 없는 버튼입니다.

@Composable
private fun PrezelFloatingButtonSample() {
    PrezelFloatingButton(
        iconSource = DrawableIcon(resId = PrezelIcons.Blank),
        style = PrezelFloatingButtonStyle(),
        onClick = {},
    )
}

PrezelFloatingMenuButtom 예시 코드

메뉴 기능이 있는 버튼입니다.

@Composable
private fun PrezelFloatingMenuButtonSample() {
    var isExpanded by remember { mutableStateOf(false) }

    PrezelFloatingMenuButton(
        iconSource = DrawableIcon(resId = PrezelIcons.Blank),
        isExpanded = isExpanded,
        onClick = { isExpanded = !isExpanded },
        style = PrezelFloatingButtonStyle(),
    ) {
        PrezelFloatingButtonMenuItem(label = "A", onClick = {}, iconSource = DrawableIcon(resId = PrezelIcons.Blank))
        PrezelFloatingButtonMenuItem(label = "B", onClick = {}, iconSource = DrawableIcon(resId = PrezelIcons.Blank))
        PrezelFloatingButtonMenuItem(label = "C", onClick = {}, iconSource = DrawableIcon(resId = PrezelIcons.Blank))
    }
}

Summary by CodeRabbit

  • 새로운 기능

    • 플로팅 버튼 컴포넌트 추가(프라이머리/세컨더리, 정규/소형) 및 풀폭 메뉴 항목 지원.
    • 확장 가능한 플로팅 메뉴 추가로 메인 버튼에서 컨텍스트 메뉴 표시 가능.
    • 드롭 섀도우 효과(시각적 그림자) 지원 추가.
  • 기타

    • 아이콘 접근성 설명 방식 변경(리소스 기반) 및 닫기 문자열 리소스 추가.
    • 정적 분석 설정에 명명 규칙 항목 추가(비활성).

✏️ Tip: You can customize this high-level summary in your review settings.

그림자 렌더링 성능을 최적화하기 위해 `drawWithCache`를 사용하는 `dropShadowCache` Modifier 확장 함수를 추가했습니다. 이 함수는 그림자 관련 Paint 및 Path 객체를 캐시하여 리컴포지션 시 불필요한 재생성을 방지합니다.

*   **기능**: `dropShadowCache` Modifier를 추가하여 Composable에 그림자 효과를 적용할 수 있도록 함
*   **파라미터**: 색상(`color`), 오프셋(`offsetX`, `offsetY`), 블러 반경(`blurRadius`), 모양(`shape`), 블러 스타일(`blurStyle`) 설정 기능 제공
*   **최적화**: `drawWithCache`를 활용하여 그림자 렌더링 성능 개선
디자인 시스템에 사용될 `PrezelFloatingActionButton`의 스타일 속성을 정의했습니다.

*   **스타일 계층(Hierarchy)**: `PRIMARY`, `SECONDARY` 두 종류의 계층을 `PrezelFloatingButtonHierarchy` 열거형으로 정의
*   **크기(Size)**: `SMALL`(36dp), `REGULAR`(48dp) 두 가지 크기를 `PrezelFloatingButtonSize` 열거형으로 정의
*   **색상**: 계층에 따라 `containerColor`와 `contentColor`를 반환하는 `@Composable` 함수 추가
*   **그림자**: `dropShadowCache`를 사용하여 공통 그림자 스타일(`applyPrezelFloatingButtonShadow`) 적용
*   **아이콘 크기**: 버튼 크기에 따라 아이콘 크기(16dp, 20dp)를 결정하는 `prezelFloatingButtonIconSize` 함수 추가
디자인 시스템에 사용될 `PrezelFloatingActionButton`의 스타일 속성을 정의했습니다.

*   **스타일 계층(Hierarchy)**: `PRIMARY`, `SECONDARY` 두 종류의 계층을 `PrezelFloatingButtonHierarchy` 열거형으로 정의
*   **크기(Size)**: `SMALL`(36dp), `REGULAR`(48dp) 두 가지 크기를 `PrezelFloatingButtonSize` 열거형으로 정의
*   **색상**: 계층에 따라 `containerColor`와 `contentColor`를 반환하는 `@Composable` 함수 추가
*   **그림자**: `dropShadowCache`를 사용하여 공통 그림자 스타일(`applyPrezelFloatingButtonShadow`) 적용
*   **아이콘 크기**: 버튼 크기에 따라 아이콘 크기(16dp, 20dp)를 결정하는 `prezelFloatingButtonIconSize` 함수 추가
디자인 시스템에 사용될 `PrezelFloatingActionButton`의 스타일 속성을 정의했습니다.

*   **스타일 계층(Hierarchy)**: `PRIMARY`, `SECONDARY` 두 종류의 계층을 `PrezelFloatingButtonHierarchy` 열거형으로 정의
*   **크기(Size)**: `SMALL`(36dp), `REGULAR`(48dp) 두 가지 크기를 `PrezelFloatingButtonSize` 열거형으로 정의
*   **색상**: 계층에 따라 `containerColor`와 `contentColor`를 반환하는 `@Composable` 함수 추가
*   **그림자**: `dropShadowCache`를 사용하여 공통 그림자 스타일(`applyPrezelFloatingButtonShadow`) 적용
*   **아이콘 크기**: 버튼 크기에 따라 아이콘 크기(16dp, 20dp)를 결정하는 `prezelFloatingButtonIconSize` 함수 추가
확장 가능한 메뉴를 포함하는 `PrezelFloatingMenuButton` 컴포저블을 추가했습니다. 이 버튼은 클릭 시 하위 메뉴 항목들을 표시하거나 숨길 수 있습니다.

*   **주요 기능**:
    *   `isExpanded` 상태에 따라 주 버튼의 아이콘이 기본 아이콘에서 `Cancel` 아이콘으로 전환됩니다.
    *   확장 메뉴(`content`)는 `AnimatedVisibility`를 사용하여 페이드 인/아웃 효과와 함께 나타납니다.
    *   메뉴 컨테이너는 흰색 배경과 둥근 모서리(`V12`) 스타일이 적용됩니다.

*   **구성 요소**:
    *   `PrezelFloatingMenuButton`: 메인 플로팅 버튼과 확장 메뉴를 포함하는 최상위 컴포저블입니다.
    *   `PrezelMainFloatingButton`: 상태에 따라 아이콘이 변경되는 주 버튼입니다.
    *   `PrezelFloatingButtonMenu`: 애니메이션 효과가 적용된 메뉴 컨테이너입니다.

*   **미리보기**: `Primary` 및 `Secondary` 계층과 `Regular`, `Small` 크기 조합에 대한 확장/축소 상태별 미리보기를 추가했습니다.
`PrezelFloatingMenuButton` 내에서 사용될 `PrezelFloatingButtonMenuItem` 컴포넌트를 추가하여, 확장된 메뉴의 각 항목을 일관된 디자인 시스템에 따라 구현할 수 있도록 개선했습니다.

*   **기능 추가**: `PrezelFloatingButtonMenuItem` 컴포저블 추가
    *   `label`, `icon`, `onClick` 액션을 설정할 수 있습니다.
    *   `PrezelFloatingButtonMenuItemSize` (`REGULAR`, `SMALL`) enum을 통해 크기(패딩, 아이콘, 텍스트 스타일)를 조절할 수 있습니다.
*   **리팩토링**: `PrezelFloatingMenuButton`의 컨텐츠 스타일링 방식 변경
    *   기존에 `LocalTextStyle`을 제공하던 방식에서 `LocalContentColor`만 제공하도록 수정했습니다.
    *   메뉴 항목의 텍스트 스타일은 새로운 `PrezelFloatingButtonMenuItem`이 직접 관리합니다.
*   **기타**: `PrezelFloatingButtonMenuItem`의 다양한 상태(아이콘 유무, 크기)를 확인할 수 있도록 Preview 코드를 추가 및 개선했습니다.
detekt-config.yml 설정 파일에서 `MatchingDeclarationName` 규칙을 비활성화하여, 파일 이름과 클래스/객체 이름이 일치하지 않아도 경고가 발생하지 않도록 수정했습니다.
`PrezelFloatingMenuButton` 컴포넌트의 스타일링 유연성을 높이고, `PrezelFloatingButtonStyle`에 정의된 계층(`hierarchy`)과 크기(`size`)에 따라 메뉴 아이템의 스타일이 동적으로 변경되도록 개선했습니다.

*   **스타일 동기화**: `PrezelFloatingMenuButton`의 `hierarchy`와 `size`가 하위 메뉴(`PrezelFloatingButtonMenu`)와 메뉴 아이템(`PrezelFloatingButtonMenuItem`)에 자동으로 반영되도록 수정했습니다.
    *   `PrezelFloatingMenuButton`의 `hierarchy`에 따라 메뉴 컨테이너의 배경색과 내부 콘텐츠(텍스트/아이콘) 색상이 변경됩니다.
    *   `PrezelFloatingMenuButton`의 `size`에 맞춰 메뉴 컨테이너의 내부 패딩과 메뉴 아이템의 크기가 조정됩니다.
*   **CompositionLocal 활용**: `LocalPrezelFloatingButtonMenuItemSize`를 추가하여, `PrezelFloatingMenuButton`의 `size`를 하위 컴포넌트인 `PrezelFloatingButtonMenuItem`으로 효율적으로 전달하도록 리팩토링했습니다. 이로 인해 `PrezelFloatingButtonMenuItem`에서 `size` 파라미터가 제거되었습니다.
*   **스타일 함수 추가**: `hierarchy`와 `size`에 따른 색상 및 패딩 값을 반환하는 `prezelFloatingMenuButtonContainerColor`, `prezelFloatingMenuButtonContentColor`, `prezelFloatingMenuButtonPaddingValues` 함수를 추가했습니다.
`PrezelFloatingButtonMenuItem`의 스타일 관련 로직을 별도의 `...Style.kt` 파일로 이동하고, `CompositionLocal`을 활용하여 스타일 속성을 관리하도록 구조를 개선했습니다.

*   **리팩토링**:
    *   `LocalPrezelFloatingButtonMenuItemSize`를 `...Style.kt` 파일로 이동시켜 컴포넌트의 의존성을 줄였습니다.
    *   `PrezelFloatingButtonMenuItem` 내부에서 사이즈(`size`)를 직접 전달받지 않고, `CompositionLocal`에서 현재 값을 가져와 스타일 함수(`prezelFloatingButtonMenuItem...`)에 적용하도록 변경했습니다.
*   **기능 추가**:
    *   아이콘과 텍스트 사이의 간격(`Spacer`)을 스타일 파일 내에서 관리하기 위해 `prezelFloatingButtonMenuItemSpaceDp` 함수를 추가했습니다.
*   **구조 개선**:
    *   기존 스타일 관련 함수들이 `size`를 필수로 요구하던 것에서 `LocalPrezelFloatingButtonMenuItemSize.current`를 기본값으로 사용하도록 변경하여 호출을 단순화했습니다.
`PrezelFloatingMenuButton` 및 하위 `PrezelFloatingButtonMenuItem`의 너비 계산 방식을 개선하여 일관된 레이아웃을 제공하도록 수정했습니다.

*   **`PrezelFloatingMenuButton`**:
    *   기존 `wrapContentSize()`를 `width(IntrinsicSize.Max)`로 변경하여, 메뉴 아이템의 너비가 콘텐츠 길이에 맞춰 자동으로 확장되도록 수정했습니다. 이를 통해 아이템들이 동일한 너비를 갖게 됩니다.
*   **`PrezelFloatingButtonMenuItem`**:
    *   `fillMaxWidth()`를 적용하여 부모 컴포넌트(`PrezelFloatingMenuButton`)에 의해 결정된 너비를 채우도록 변경했습니다.
`PrezelFloatingButtonMenuItem` 컴포넌트의 Row에 `PrezelTheme.shapes.V6`를 사용하여 clip을 적용했습니다. 이를 통해 클릭 시 ripple 효과가 아이템의 둥근 모서리 영역을 벗어나지 않도록 수정했습니다.
`PrezelFloatingMenuButton`의 Preview에서 버튼을 클릭하면 확장/축소 상태가 실제로 변경되도록 상호작용 기능을 추가했습니다.

*   `remember`와 `mutableStateOf`를 사용하여 프리뷰 내에서 `isExpanded` 상태를 관리합니다.
*   `onClick` 람다에서 상태를 토글하도록 수정하여 UI 변경을 바로 확인할 수 있게 개선했습니다.
@moondev03 moondev03 self-assigned this Jan 23, 2026
@moondev03 moondev03 added the ✨ feat 새로운 기능 추가 또는 기존 기능 확장 label Jan 23, 2026
@moondev03 moondev03 linked an issue Jan 23, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

Walkthrough

플로팅 버튼 컴포넌트와 관련 스타일 유틸리티를 추가합니다. 공개 컴포저블로 PrezelFloatingButton, PrezelFloatingMenuButton, PrezelFloatingButtonMenuItem 및 관련 스타일 열거형(크기·계층)과 데이터 클래스가 도입되었고, 메뉴 항목 전용 스타일 헬퍼(패딩·아이콘 크기 등)와 Modifier.dropShadowCache 유틸이 추가되었습니다. IconSource 인터페이스의 contentDescription이 프로퍼티에서 @Composable 함수로 변경되었고, DrawableIcon이 리소스 기반 설명을 반환하도록 업데이트되며 관련 문자열 리소스와 detekt 설정 항목이 추가되었습니다.

Possibly related PRs

  • Team-Prezel/Prezel-Android PR 25: IconSource 및 버튼 컴포넌트 관련 API 변경을 도입한 PR로, 본 PR의 contentDescription API 리팩터 및 버튼 사용부와 코드 수준에서 직접 연관됩니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목 'PrezelFloatingButton 구현'은 PR의 주요 변경 사항인 PrezelFloatingButton 컴포넌트 구현을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 모든 필수 섹션(작업 내용, 관련 이슈, 스크린샷, 비고)을 포함하고 있으며, 구현 내용과 사용 예시가 상세히 작성되어 있습니다.
Linked Issues check ✅ Passed PR의 모든 주요 변경사항(Modifier.dropShadowCache, PrezelFloatingButton, 메뉴 컴포넌트들, 스타일 구현)이 이슈 #23의 목표를 충족하고 있습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #23의 요구사항과 직접적으로 관련되어 있으며, 범위를 벗어난 변경은 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt`:
- Around line 20-41: The Icon's contentDescription can be null which breaks
accessibility; update PrezelFloatingButton to require a non-null
contentDescription (add a contentDescription: String parameter to
PrezelFloatingButton and pass it to Icon) or alternatively make
IconSource.contentDescription non-null across implementations (e.g., change
IconSource.contentDescription to String and update DrawableIcon), but choose one
approach and update all call sites so Icon(contentDescription =
contentDescription) always receives a non-null value (referencing
PrezelFloatingButton, Icon, IconSource.contentDescription, and DrawableIcon).

In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonStyle.kt`:
- Around line 73-81: The PRIMARY branch in prezelFloatingMenuButtonContentColor
currently uses a hardcoded PrezelColorScheme.Light.textMedium which bypasses
active theme palettes; change the PRIMARY case to use the passed-in
colors.textMedium (the same source used for SECONDARY) so the function respects
the current PrezelTheme colors instead of the fixed Light scheme.

In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt`:
- Around line 65-81: The hardcoded Korean label for the close icon should be
moved to a string resource and accessed via stringResource: add an entry in
designsystem's res/values/strings.xml (e.g. name="floating_button_close"), then
update PrezelMainFloatingButton to call
stringResource(R.string.floating_button_close) and pass that value to
DrawableIcon(..., contentDescription = ...); reference the
PrezelMainFloatingButton function, the currentIconSource assignment, and
PrezelIcons.Cancel when making this change and ensure the necessary
androidx.compose.ui.res.stringResource import is added.
🧹 Nitpick comments (2)
Prezel/detekt-config.yml (1)

50-51: 규칙 전체 비활성화 대신 더 세밀한 설정 고려

MatchingDeclarationName 규칙을 전체적으로 비활성화하면 코드베이스 전반에서 파일명과 선언명 간의 일관성이 저하될 수 있습니다. 특정 파일이나 디렉토리에서만 예외를 허용하는 것이 더 안전한 접근입니다.

♻️ 대안: excludes를 사용한 세밀한 설정
     MatchingDeclarationName:
-        active: false
+        active: true
+        excludes:
+            - '**/floatingbutton/**'

또는 해당 파일들을 규칙에 맞게 재구성하는 방법도 고려해 보세요.

Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt (1)

55-77: 프리뷰 중복 간소화 고려

프리뷰에서 동일 패턴의 호출이 반복되어 리스트로 묶으면 가독성이 좋아집니다.

♻️ 예시 리팩토링
         ) {
-            PrezelFloatingButton(
-                iconSource = DrawableIcon(resId = PrezelIcons.Blank),
-                style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.REGULAR),
-                onClick = {},
-            )
-
-            PrezelFloatingButton(
-                iconSource = DrawableIcon(resId = PrezelIcons.Blank),
-                style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.SMALL),
-                onClick = {},
-            )
-
-            PrezelFloatingButton(
-                iconSource = DrawableIcon(resId = PrezelIcons.Blank),
-                style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.REGULAR),
-                onClick = {},
-            )
-
-            PrezelFloatingButton(
-                iconSource = DrawableIcon(resId = PrezelIcons.Blank),
-                style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.SMALL),
-                onClick = {},
-            )
+            listOf(
+                PrezelFloatingButtonStyle(PrezelFloatingButtonHierarchy.PRIMARY, PrezelFloatingButtonSize.REGULAR),
+                PrezelFloatingButtonStyle(PrezelFloatingButtonHierarchy.PRIMARY, PrezelFloatingButtonSize.SMALL),
+                PrezelFloatingButtonStyle(PrezelFloatingButtonHierarchy.SECONDARY, PrezelFloatingButtonSize.REGULAR),
+                PrezelFloatingButtonStyle(PrezelFloatingButtonHierarchy.SECONDARY, PrezelFloatingButtonSize.SMALL),
+            ).forEach { style ->
+                PrezelFloatingButton(
+                    iconSource = DrawableIcon(resId = PrezelIcons.Blank),
+                    style = style,
+                    onClick = {},
+                )
+            }
         }

HamBeomJoon
HamBeomJoon previously approved these changes Jan 24, 2026
Copy link
Contributor

@HamBeomJoon HamBeomJoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니당

`IconSource` 인터페이스와 `DrawableIcon` 구현을 리팩터링하여 콘텐츠 설명(content description)을 유연하게 처리하도록 개선했습니다.

*   **구조 변경**: `IconSource` 인터페이스의 `contentDescription` 프로퍼티를 `@Composable` 함수인 `contentDescription()`으로 변경했습니다.
*   **기능 추가**: `DrawableIcon`에 `@StringRes` 타입의 `contentDescTextId` 파라미터를 추가하여, 문자열 리소스를 통해 콘텐츠 설명을 제공할 수 있도록 지원합니다.
*   **동작 변경**: 기존에 `DrawableIcon`에 직접 문자열로 전달하던 `contentDescription`을 제거하고, `contentDescription()` 함수 내에서 `stringResource`를 호출하여 처리하도록 수정했습니다.
하드코딩 되어있던 `PrezelFloatingMenuButton`의 "플로팅 버튼 닫기" Content Description을 `strings.xml` 리소스로 추출하여 관리하도록 수정했습니다.

*   **주요 변경 사항**:
    *   `core/designsystem` 모듈에 `strings.xml` 파일 추가 및 `close_floating_btn_content_desc` 문자열 리소스 정의.
    *   `PrezelFloatingMenuButton`에서 확장 상태(`isExpanded`)일 때, 하드코딩된 문자열 대신 `R.string.close_floating_btn_content_desc` 리소스를 참조하도록 변경.
`IconSource`의 `contentDescription` 프로퍼티 접근 방식을 직접 참조에서 함수(`contentDescription()`) 호출로 변경하여 일관성을 확보하고 향후 확장을 용이하게 했습니다.

*   `PrezelFloatingButtonMenuItem`
*   `PrezelButtonStyle`
*   `PrezelFloatingButton`

위 컴포넌트들에서 `Icon`의 `contentDescription`을 `iconSource.contentDescription()`으로 수정했습니다.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt`:
- Around line 212-227: In PreviewFloatingMenuButton the local variable
iconSource is created but not used; update the PrezelFloatingMenuButton(...)
call to pass iconSource (the variable) into the iconSource parameter instead of
constructing a new DrawableIcon, or if the variable is unnecessary remove its
declaration; refer to PreviewFloatingMenuButton, the iconSource variable, the
PrezelFloatingMenuButton(...) call and the PrezelFloatingButtonMenuItem usages
when making the change.
♻️ Duplicate comments (1)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt (1)

74-75: 문자열 리소스 사용으로 로컬라이징 지원 - 이전 리뷰 의견 해결됨

하드코딩된 한국어 텍스트 "플로팅 버튼 닫기"가 R.string.close_floating_btn_content_desc 리소스로 올바르게 외부화되었습니다.

🧹 Nitpick comments (3)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt (1)

20-43: 접근성 개선 확인 - 하지만 여전히 nullable입니다.

IconSource.contentDescription()이 이제 @Composable 함수로 변경되어 문자열 리소스를 통한 로컬라이징을 지원합니다. 그러나 반환 타입이 여전히 String?이므로 contentDescTextId를 제공하지 않으면 스크린 리더에서 버튼 설명이 누락될 수 있습니다.

호출 측에서 접근성을 위해 contentDescTextId를 반드시 제공하도록 문서화하거나, 향후 필수 매개변수로 변경하는 것을 고려해 주세요.

Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt (1)

27-29: contentDescTextId 참조 시 it 대신 명시적 변수 사용 권장

현재 구현이 정확하지만, let 블록 내에서 it 대신 contentDescTextId를 직접 참조하고 있습니다. 이는 동작에 문제가 없으나, 일관성을 위해 it을 사용하거나 명시적 람다 파라미터를 사용하는 것이 좋습니다.

♻️ 제안된 변경
     `@Composable`
-    override fun contentDescription(): String? = contentDescTextId?.let { stringResource(contentDescTextId) }
+    override fun contentDescription(): String? = contentDescTextId?.let { stringResource(it) }
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt (1)

186-188: 파라미터와 동일한 이름의 변수 섀도잉

isExpanded 파라미터를 동일한 이름의 var로 섀도잉하고 있습니다. 코드가 동작하지만, 파라미터와 로컬 상태를 구분하기 어려워 가독성이 떨어집니다.

♻️ 변수명 변경 제안
 `@Composable`
 private fun PreviewFloatingMenuButton(
-    isExpanded: Boolean,
+    initialExpanded: Boolean,
     style: PrezelFloatingButtonStyle,
 ) {
-    var isExpanded by remember { mutableStateOf(isExpanded) }
+    var isExpanded by remember { mutableStateOf(initialExpanded) }

`IconSource` 인터페이스와 그 구현체인 `ResIconSource`에서 `contentDescription` 함수의 파라미터를 변경하여, 동적인 포맷 인자(format arguments)를 전달할 수 있도록 개선했습니다.

*   **`IconSource` 인터페이스**: `contentDescription()` 함수에 가변 인자(vararg) `args: String`를 추가했습니다.
*   **`ResIconSource` 클래스**: `stringResource` 호출 시 전달받은 `args`를 포함하도록 수정하여, 문자열 리소스에 동적 값을 삽입할 수 있게 되었습니다.
`PrezelFloatingMenuButton.kt` 파일 내 Preview용 컴포저블 함수인 `PreviewFloatingMenuButton`의 파라미터명을 더 명확하게 수정했습니다.

*   `isExpanded` 파라미터명을 `initialExpanded`로 변경하여, 상태의 초기값을 설정하는 역할을 명확히 표현했습니다.
*   이 변경 사항을 `PrimaryFloatingMenuButtonPreview`와 `SecondaryFloatingMenuButtonPreview` 내 호출부에 반영했습니다.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt`:
- Line 29: contentDescription 함수의 현재 구현 passes the args array as a single
parameter to stringResource, so format placeholders aren't filled; change the
call in IconSource.contentDescription to pass the vararg elements using the
spread operator (*) when forwarding args (i.e., use stringResource(resId,
*args)) so contentDescTextId and stringResource receive the vararg values
correctly.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@HamBeomJoon HamBeomJoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@moondev03 moondev03 merged commit 6d89a27 into develop Jan 24, 2026
2 checks passed
@moondev03 moondev03 deleted the feat/#23-prezel_floating_button branch January 24, 2026 11:55
@coderabbitai coderabbitai bot mentioned this pull request Jan 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가 또는 기존 기능 확장

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PrezelFloatingButton 구현

3 participants