Skip to content

feat(IconButton): 토큰 기반 사이즈/인터랙션 정책 재구성 및 모디파이어·토큰 API 추가#497

Merged
knine79 merged 13 commits into
release/4.0.0from
feature/WRP-924
Jun 1, 2026
Merged

feat(IconButton): 토큰 기반 사이즈/인터랙션 정책 재구성 및 모디파이어·토큰 API 추가#497
knine79 merged 13 commits into
release/4.0.0from
feature/WRP-924

Conversation

@knine79
Copy link
Copy Markdown
Contributor

@knine79 knine79 commented May 28, 2026

개요

IconButton의 사이즈/인터랙션 영역 산정을 하드코딩 방식에서 디자인 토큰 기반 icon-first 모델로 재구성하고, 이를 지원하는 모디파이어와 토큰 SSoT API를 함께 추가한다.

수정사항

IconButton 사이즈/인터랙션 정책

  • 사이즈 정책을 토큰 기반 icon-first 모델로 재구성
  • interactionExpansion 제거 → interactionSize/interactionRadius 도입
  • normal variant: iconSize × 1.5 보다 큰 첫번째 dimension 토큰으로 interaction(터치) 영역 산정, WCAG 24×24 최소 영역 보장
  • normal variant: interactionSize × 0.3 보다 작은 첫번째 radius 토큰으로 모서리 반경 산정
  • background variant: size 파라미터를 "음영 포함 전체 크기"로 정정 (Blueprint 기본값 24→20 조정)

모디파이어 추가

  • disableInteraction / interactionColor 모디파이어 추가 (토큰 SSoT 참조)

토큰 SSoT API

  • Dimension/Spacing/Radius/Primitive/Opacity에 allValues·min·max 노출 (토큰 스냅·최대/최소 도출용)
  • PrimitiveallValuesprimitiveInfinity가 포함되어, 유한 최대값이 필요한 범위·슬라이더 제약 계산을 위해 max 대신 finiteMax 제공
  • 누락된 dimension12 토큰 추가

버그 수정

  • normal+custom에서 outlined 전환 시 발생하던 크래시 수정
  • background variant에서 지정한 크기가 음영을 포함한 전체 크기가 되도록 조정
  • 내부 backgrounOutset 오타를 backgroundOutset으로 수정

Blueprint / 문서

  • IconButtonPreview 새 인터페이스 옵션 추가 (disableInteraction/interactionColor 등)
  • IconButtonPreview 커스텀 사이즈 슬라이더 범위를 컴포넌트 정책(24...64)에 맞춤
  • 코드 및 docstring 정합성 정리
  • DocC 문서 및 MCP 토큰 데이터 재생성

미리보기

작업 전 작업 후
스크린샷 스크린샷

@knine79 knine79 self-assigned this May 28, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Review Change Stack

Walkthrough

IconButton의 사용자 상호작용 제어 메서드(disableInteraction, interactionColor)를 추가하고 metrics 기반 레이아웃으로 재구성했습니다. 동시에 Dimension 등 5개 토큰 유틸리티에 allValues/min/max를 확장하고, 프리뷰의 사이즈 로직을 간결하게 정리하며, 한국어 로컬라이제이션과 문서를 정비했습니다.

Changes

IconButton 상호작용 제어 및 레이아웃 재설계

Layer / File(s) Summary
상호작용 제어 API 추가 및 저장 상태 확장
Sources/Montage/1 Components/2 Actions/IconButton.swift
disableInteraction(:) 및 interactionColor(:) 메서드를 공개 API로 추가하고, 초기화 로직에서 해당 상태를 저장하도록 확장했습니다.
Variant 패턴 정리 및 보조 색상 계산
Sources/Montage/1 Components/2 Actions/IconButton.swift
showPushBadge(:)와 borderColor(:)의 Variant 연관값 바인딩을 단순화하고, _iconColor와 _strokeColor 계산 로직을 새 토큰 기준으로 재구성했습니다.
Variant.metrics 기반 레이아웃 및 배경 렌더링
Sources/Montage/1 Components/2 Actions/IconButton.swift
아이콘 프레임/패딩/클리핑이 metrics 기반으로 계산되고, 배경 렌더링이 backgroundLayer(metrics:)로 분리되며, Interaction 상태가 disableInteraction 플래그를 반영하도록 변경되었습니다.
Variant 메트릭 계산 및 색상 매핑
Sources/Montage/1 Components/2 Actions/IconButton.swift
Variant.metrics가 container/padding/radius/icon을 클램프 및 토큰 선택으로 도출하고, disabledBackgroundColor/disabledIconColor/interactionVariant를 새 토큰 기준으로 매핑하며, Variant.background의 size 기본값을 32로 설정했습니다.

토큰 유틸리티 allValues/min/max 확장

Layer / File(s) Summary
Dimension 토큰 확장 및 dimension12 추가
Sources/Montage/1 Components/9 Utilities/Dimension.swift
Dimension 열거형에 allValues/min/max 를 추가하고, CGFloat 확장에 dimension12(12pt) 토큰을 문서 주석과 함께 추가했습니다.
Opacity, Primitive, Radius, Spacing 토큰 확장
Sources/Montage/1 Components/9 Utilities/Opacity.swift, Sources/Montage/1 Components/9 Utilities/Primitive.swift, Sources/Montage/1 Components/9 Utilities/Radius.swift, Sources/Montage/1 Components/9 Utilities/Spacing.swift
Opacity, Primitive, Radius, Spacing 각 열거형에 allValues 배열과 min/max 계산 프로퍼티를 추가하여 토큰 범위를 일관되게 제공합니다. Primitive는 finiteMax(유한값 최대)를 별도로 제공합니다.

IconButton 프리뷰 및 상태 관리 재구성

Layer / File(s) Summary
프리뷰 상태 로직 및 사이즈 결정
Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
customSize 기본값을 36으로 변경하고, variantIndex 기반으로 isCustomSize를 계산하며, resolvedNormalSize/resolvedSize로 실제 아이콘 사이즈를 선택하도록 로직을 재구성했습니다.
프리뷰 렌더링 및 옵션 UI
Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
IconButton 적용에 disableInteraction 및 interactionColor를 추가하고, 옵션 패널에서 variantIndex에 따라 커스텀 사이즈 슬라이더(24...64)를 분기 렌더링하며, 토글 UI를 disableInteraction으로 변경하고 interactionColor 선택을 추가했습니다.

한국어 로컬라이제이션 및 문서 정비

Layer / File(s) Summary
한국어 로컬라이제이션 추가
Sources/Montage/Asset/Localizable.xcstrings
빈 문자열, 템플릿 문자열(%@ %@, %@ %lld), 및 UI 문구(슬라이더, 아이콘, 오류, 로딩 중 등) 키에 대한 한국어(ko) 로컬라이제이션 블록을 추가했습니다.
IconButton 문서 수정 및 메서드 문서 추가
documentation/components/actions/iconbutton/ios.md
"Outlined, soild" 오타를 수정하고, 컨테이너 커스텀 범위를 24~64pt로 명시하며, disableInteraction(Bool)/interactionColor(Color.Semantic) 메서드 문서를 추가하고, NormalSize/Size/Variant.background 크기 설명을 구체화했습니다.
토큰 유틸리티 문서 및 MCP 메타데이터 업데이트
documentation/utilities/ios-extensions/corefoundation.md, documentation/utilities/ios-utility-components/dimension.md, documentation/utilities/ios-utility-components/opacity.md, documentation/utilities/ios-utility-components/primitive.md, documentation/utilities/ios-utility-components/radius.md, documentation/utilities/ios-utility-components/spacing.md, packages/montage-mcp/data/components.json, packages/montage-mcp/data/tokens.json
Dimension, Opacity, Primitive, Radius, Spacing 토큰의 allValues/min/max에 대한 Topics 섹션을 문서에 추가하고, IconButton의 disableInteraction/interactionColor를 components.json에 추가하며, tokens.json의 각 토큰에 Type Properties 섹션 메타데이터를 반영했습니다.

예상 코드 리뷰 노력

🎯 4 (Complex) | ⏱️ ~50 분

관련 PR

  • wanteddev/montage-ios#486: Dimension, Primitive, Radius, Spacing, Opacity 토큰 유틸리티의 allValues/min/max 구현과 동일 코드 영역의 토큰 네임스페이스 확장이 직접 연관됩니다.
  • wanteddev/montage-ios#485: IconButtonPreview의 normalSizeIndex/resolvedNormalSize 도입 및 normal 사이즈 분기 로직을 상속하여 variantIndex 기반의 isCustomSize 로직으로 재구성한 부분이 직접 관련됩니다.

추천 라벨

AI Review Completed

추천 리뷰어

  • jhseo
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed PR 제목은 변경사항의 핵심(토큰 기반 사이즈/인터랙션 정책 재구성 및 모디파이어·토큰 API 추가)을 명확하고 간결하게 설명하며, raw_summary의 다양한 파일 변경사항들을 잘 요약하고 있습니다.
Description check ✅ Passed PR 설명은 개요, 수정사항, 추가된 모디파이어, 토큰 API 변경 등 변경사항과 직접적으로 관련된 상세 내용을 포함하고 있으며, 이슈 링크 및 스크린샷 참조도 제공하고 있습니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/WRP-924

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

@knine79 knine79 force-pushed the feature/WRP-924 branch from 973bfcd to 3871890 Compare May 28, 2026 10:36
@github-actions github-actions Bot added the in review This issue requires a review. label May 28, 2026
Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Montage/1` Components/2 Actions/IconButton.swift:
- Around line 170-172: interactionSize is calculated as variant.interactionSize
+ 2 * padding but the final .frame uses + padding only once, causing mismatch
between visual padding and touch area; update the .frame size calculations
(where .frame is using + padding) to add 2 * padding (or use interactionSize
directly) so it matches .padding(.all, variant.backgroundOutset + padding) and
the interactionSize definition; apply the same change to the other occurrence
that mirrors lines 212-213, ensuring consistency between interactionSize,
padding, and frame sizing.
- Around line 439-443: Variant.background can produce negative frame sizes when
size is small; update the calculation in IconButton.swift to clamp the inner
dimension so it never goes negative by computing an innerSize = max(0,
CGFloat(size) - backgroundOutset * 2) (or enforce size >= backgroundOutset*2)
and use innerSize for width and height; reference the Variant.background case
and the backgroundOutset constant when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2ea5c0d3-d657-45ad-b0f4-2249eb0ba241

📥 Commits

Reviewing files that changed from the base of the PR and between 53f26e3 and 3871890.

📒 Files selected for processing (7)
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Montage/1 Components/2 Actions/IconButton.swift
  • Sources/Montage/1 Components/9 Utilities/Dimension.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • documentation/components/actions/iconbutton/ios.md
  • documentation/utilities/ios-extensions/corefoundation.md
  • packages/montage-mcp/data/components.json

Comment thread Sources/Montage/1 Components/2 Actions/IconButton.swift Outdated
Comment thread Sources/Montage/1 Components/2 Actions/IconButton.swift Outdated
@github-actions github-actions Bot added accepted This issue has been reviewed. and removed in review This issue requires a review. labels Jun 1, 2026
Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift`:
- Line 181: The preview Slider currently uses a range of 10...100 which doesn't
match IconButton's actual custom container limits; update the Slider range(s) in
IconButtonPreview where customSize is bound (the SwiftUI.Slider instances around
lines referencing customSize) to use 24...64 so the preview values match the
real IconButton container range and rendering; locate the SwiftUI.Slider(value:
$customSize, ...) usages in IconButtonPreview and change their in: parameter to
24...64.

In `@Sources/Montage/1` Components/9 Utilities/Primitive.swift:
- Around line 30-41: Primitive.max currently returns the last value from
allValues which includes .primitiveInfinity, causing max to be infinite and
unsuitable for range/slider calculations; change the implementation so max
returns the largest finite primitive token (e.g., compute the last finite
element of allValues or add a new property like maxFinite) by filtering out
infinite values (use isFinite) and falling back to 0 if none found; keep
Primitive.min unchanged and reference allValues and primitiveInfinity when
locating the code to update.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aedba78b-8aff-454d-afd9-baeecca41db3

📥 Commits

Reviewing files that changed from the base of the PR and between 3871890 and f859bfe.

📒 Files selected for processing (15)
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Montage/1 Components/2 Actions/IconButton.swift
  • Sources/Montage/1 Components/9 Utilities/Dimension.swift
  • Sources/Montage/1 Components/9 Utilities/Opacity.swift
  • Sources/Montage/1 Components/9 Utilities/Primitive.swift
  • Sources/Montage/1 Components/9 Utilities/Radius.swift
  • Sources/Montage/1 Components/9 Utilities/Spacing.swift
  • documentation/components/actions/iconbutton/ios.md
  • documentation/utilities/ios-utility-components/dimension.md
  • documentation/utilities/ios-utility-components/opacity.md
  • documentation/utilities/ios-utility-components/primitive.md
  • documentation/utilities/ios-utility-components/radius.md
  • documentation/utilities/ios-utility-components/spacing.md
  • packages/montage-mcp/data/components.json
  • packages/montage-mcp/data/tokens.json
✅ Files skipped from review due to trivial changes (3)
  • Sources/Montage/1 Components/9 Utilities/Spacing.swift
  • documentation/utilities/ios-utility-components/spacing.md
  • documentation/utilities/ios-utility-components/primitive.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/montage-mcp/data/components.json

Comment thread Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift Outdated
Comment thread Sources/Montage/1 Components/9 Utilities/Primitive.swift Outdated
@github-actions github-actions Bot added in review This issue requires a review. and removed accepted This issue has been reviewed. labels Jun 1, 2026
@knine79 knine79 marked this pull request as ready for review June 1, 2026 03:04
@knine79 knine79 requested a review from a team as a code owner June 1, 2026 03:04
@knine79 knine79 requested review from jhseo and removed request for a team June 1, 2026 03:04
@github-actions github-actions Bot added the accepted This issue has been reviewed. label Jun 1, 2026
@github-actions github-actions Bot removed the in review This issue requires a review. label Jun 1, 2026
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift (1)

45-54: 💤 Low value

variantIndex == 1 분기의 isCustomSize는 사용되지 않는 경로입니다.

background variant(variantIndex == 1)에서는 커스텀 슬라이더가 Line 185-190에서 isCustomSize와 무관하게 항상 렌더링됩니다. 따라서 case 1: true 분기는 실제로 참조되지 않는 죽은 로직입니다. 동작에는 영향이 없으나, 의도를 명확히 하려면 주석으로 표시하거나 background를 별도 처리하는 편이 읽기 쉽습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift` around
lines 45 - 54, The case for variantIndex == 1 in the isCustomSize computed
property is dead code because the background variant renders the custom slider
independently; update isCustomSize (or the surrounding logic) to remove or
clarify this branch: either remove the `case 1: true` branch and let only the
relevant branches decide custom sizing (keep `case 0` and `default` logic), or
explicitly return false for `case 1` and add a short comment on why background
is handled elsewhere (reference the isCustomSize computed property and the
background variant behavior in IconButtonPreview).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift`:
- Around line 45-54: The case for variantIndex == 1 in the isCustomSize computed
property is dead code because the background variant renders the custom slider
independently; update isCustomSize (or the surrounding logic) to remove or
clarify this branch: either remove the `case 1: true` branch and let only the
relevant branches decide custom sizing (keep `case 0` and `default` logic), or
explicitly return false for `case 1` and add a short comment on why background
is handled elsewhere (reference the isCustomSize computed property and the
background variant behavior in IconButtonPreview).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ec23fae3-fcf4-460d-b748-deed52f83c95

📥 Commits

Reviewing files that changed from the base of the PR and between f859bfe and a98b7a3.

📒 Files selected for processing (4)
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Montage/1 Components/9 Utilities/Primitive.swift
  • documentation/utilities/ios-utility-components/primitive.md
  • packages/montage-mcp/data/tokens.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • documentation/utilities/ios-utility-components/primitive.md
  • packages/montage-mcp/data/tokens.json

@knine79 knine79 changed the title feat(IconButton): interactionSize/Radius 산정 정책 갱신 feat(IconButton): 토큰 기반 사이즈/인터랙션 정책 재구성 및 모디파이어·토큰 API 추가 Jun 1, 2026
@knine79 knine79 merged commit f4d5151 into release/4.0.0 Jun 1, 2026
5 checks passed
@knine79 knine79 deleted the feature/WRP-924 branch June 1, 2026 04:31
@knine79 knine79 added this to the 4.0.0 milestone Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted This issue has been reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant