Skip to content

refactor: Blueprint 프리뷰 옵션 행 공용 컴포넌트화#517

Merged
knine79 merged 16 commits into
release/4.0.0from
refactor/blueprint-preview-layout
Jul 6, 2026
Merged

refactor: Blueprint 프리뷰 옵션 행 공용 컴포넌트화#517
knine79 merged 16 commits into
release/4.0.0from
refactor/blueprint-preview-layout

Conversation

@knine79

@knine79 knine79 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

개요

  • 이슈 링크 :

Blueprint 샘플 앱의 각 프리뷰가 제각각 작성하던 옵션 행(raw Switch/SegmentedControl/Slider/TextField/ColorPicker/Menu 등)을 공용 OptionRow 컴포넌트로 통합했습니다.

수정사항

공용 헬퍼 (PreviewOption.swift)

  • SegmentedOptionRow / SegmentedIndexRow: title 옵셔널화(라벨 없이 다른 컨트롤 옆 인라인 배치 가능), onSelect 콜백 추가
  • SliderOptionRow: onEditingEnded 콜백 추가
  • TextFieldOptionRow: placeholder 추가
  • 신규: ColorPickerOptionRow, MenuOptionRow(+ accessory), TextAreaOptionRow, PrevNextOptionRow
  • PreviewLayout: optionsEmptyView이면 "Options" 헤더를 그리지 않음

적용

  • 다수 프리뷰의 raw 옵션 컨트롤을 위 헬퍼로 교체 (ActionArea·Chip·FilterButton·Loading·Popup·Select·Skeleton·PageCounter·PaginationDots·ProgressIndicator·PushBadge·Control·DateTimePicker·BottomSheet·ProgressTracker 등)
  • Prev/Next 버튼 4곳을 PrevNextOptionRow로 통합
  • HorizontalProgressTracker step 라벨 입력을 TextAreaOptionRow로 교체

기타 (별도 커밋)

  • fix: 단일 Slider headingLabel을 highValue만 표시하도록 정정
  • refactor: TopNavigation 미사용 navigationBar 코드 제거 및 기본 배경 정리

미리보기

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

@knine79 knine79 self-assigned this Jun 26, 2026
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

PreviewLayoutPreviewOption 공통 유틸리티를 추가하고, Blueprint 프리뷰 화면들을 새 레이아웃 구조로 전환했습니다. 동시에 컴포넌트 목록 라우팅과 프로젝트 구성이 갱신됐고, Montage의 Slider, TextArea, Thumbnail, TopNavigation 및 관련 메타데이터도 함께 정리됐습니다.

Changes

PreviewLayout 인프라 및 프로젝트/라우팅 갱신

Layer / File(s) Summary
PreviewLayout · PreviewOption 추가
Sources/Blueprint/Sources/Utilities/PreviewLayout.swift, Sources/Blueprint/Sources/Utilities/PreviewOption.swift
PreviewLayout이 stacked/upsideDown/floating/navigation 모드로 프리뷰와 옵션을 배치하고, 환경 기반 체커 설정과 navigation/floating 보조 UI를 제공합니다. PreviewOption은 세그먼트, 토글, 슬라이더, 텍스트 입력, 색상 선택, 메뉴, 이전/다음 행 컴포넌트를 추가합니다.
프로젝트 파일과 목록 라우팅 갱신
Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj, Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift, Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
Xcode 프로젝트에서 PaginationPreviewProgressTrackerPreview 항목이 제거되고 PreviewLayout·PreviewOptionUtilities에 추가됩니다. ComponentSection의 케이스와 분류가 새 프리뷰 대상에 맞게 바뀌고, ComponentListNavigationCoordinator의 destination 매핑도 갱신됩니다.

콘텐츠·스타일 프리뷰 전환

Layer / File(s) Summary
콘텐츠·스타일 프리뷰 전환
Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift, AvatarPreview.swift, AvatarGroupPreview.swift, CardPreview.swift, CategoryPreview.swift, ChipPreview.swift, ColorPreview.swift, ContentBadgePreview.swift, FallbackViewPreview.swift, FramedStylePreview.swift, IconPreview.swift, ListCardPreview.swift, ListCellPreview.swift, PlayBadgePreview.swift, PushBadgePreview.swift, SectionHeaderPreview.swift, ShadowPreview.swift, SkeletonPreview.swift, ThumbnailPreview.swift
여러 콘텐츠·스타일 프리뷰가 ScrollView 기반 수동 UI에서 PreviewLayout과 옵션 행 컴포넌트로 전환되며, showTransparentChecker 상태와 관련 modifier가 제거됩니다. ColorPreview는 색상 타입 선택 인덱스로 바뀌고 ThumbnailPreview는 라벨 포맷용 description을 추가합니다.

선택·입력·내비게이션 프리뷰 전환

Layer / File(s) Summary
선택·입력·내비게이션 프리뷰 전환
Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift, ControlPreview.swift, FilterButtonPreview.swift, FlowLayoutPreview.swift, IconButtonPreview.swift, LoadingPreview.swift, ModalNavigationPreview.swift, PageCounterPreview.swift, PaginationDotsPreview.swift, PopoverPreview.swift, PopupPreview.swift, ProgressIndicatorPreview.swift, PullToRefreshPreview.swift, SelectPreview.swift, SliderPreview.swift, SnackBarPreview.swift, TabPreview.swift, TextAreaPreview.swift, TextButtonPreview.swift, TextFieldPreview.swift, ToastPreview.swift, TooltipPreview.swift, VerticalProgressTrackerPreview.swift, HorizontalProgressTrackerPreview.swift, DateTimePickerPreview.swift, PlayBadgePreview.swift, ShadowPreview.swift, SkeletonPreview.swift, TopNavigationPreview.swift
선택·입력·내비게이션 계열 프리뷰가 PreviewLayout과 옵션 행으로 전환됩니다. SelectshowSheet를 추가하고 LoadingonChange 기반 자동 종료가 도입되며, Popup은 지연 재표시 흐름이 제거됩니다. 진행 트래커와 상단 내비게이션 프리뷰도 새 옵션 구조로 재배선됩니다.

Montage API와 메타데이터 정리

Layer / File(s) Summary
Montage API와 메타데이터 정리
Sources/Montage/1 Components/3 Selection And Input/Slider.swift, TextArea.swift, Sources/Montage/1 Components/4 Contents/Thumbnail.swift, Sources/Montage/1 Components/6 Navigations/TopNavigation.swift, Sources/Montage/Asset/Localizable.xcstrings, packages/montage-mcp/data/components.json, packages/montage-mcp/data/tokens.json, scripts/build_mcp_data.js, .gitignore
Slider, TextArea, Thumbnail, TopNavigation 구현이 정리되고, 로컬라이제이션과 MCP components/tokens 메타데이터가 업데이트됩니다. DocC 추출 스크립트는 상속 멤버 필터링과 nested instanceProperties 수집을 지원하도록 바뀝니다. .gitignore에는 packages/.DS_Store가 추가됩니다.

추정 코드 리뷰 노력

🎯 4 (Complex) | ⏱️ ~60 minutes

연관 가능성이 있는 PR

  • wanteddev/montage-ios#513: IconPreview의 색상 제어 방식이 바뀐 흐름이 이 PR의 프리뷰 레이아웃 전환과 같은 코드 경로를 공유합니다.

제안된 리뷰어

  • agiletalk
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.33% 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 프리뷰 옵션 행을 공용 컴포넌트로 묶는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 공용 OptionRow 도입과 적용 범위가 변경사항과 잘 맞아 관련성이 높습니다.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/blueprint-preview-layout

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift (1)

27-45: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

원자 색상으로 바뀔 때 체커 상태도 함께 초기화해 주세요.

Line 37처럼 버튼만 비활성화하면, semantic/all에서 켜 둔 showTransparentChecker가 그대로 남아서 atomic 섹션에도 체커가 계속 렌더링됩니다. 세그먼트 선택이 .atomic으로 바뀌는 순간 showTransparentChecker = false까지 같이 처리해야 옵션 상태와 실제 프리뷰가 맞습니다.

🤖 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/ColorPreview.swift` around lines 27
- 45, When the selected color type changes to .atomic in ColorPreview, the
transparent checker state must be reset as well. Update the selection handling
around selectedColorTypeIndex so that switching to the atomic case also sets
showTransparentChecker to false, instead of only disabling the checkerboard
Button. Use the existing ColorPreview, selectedColorTypeIndex,
showTransparentChecker, and ColorType.allCases references to locate the logic
and keep the preview state aligned with the active segment.
🟡 Minor comments (12)
Sources/Montage/1 Components/5 Loading/Skeleton.swift-222-226 (1)

222-226: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

라인 수 계산에 round 대신 floor를 사용해 주세요.

현재 높이가 1.5줄보다 조금만 커도 2줄로 반올림되어 컨테이너보다 큰 스켈레톤이 그려질 수 있습니다.

수정 제안
-                            : max(1, Int(round(proxy.size.height / scaledLineHeight)))
+                            : max(1, Int(floor(proxy.size.height / scaledLineHeight)))
🤖 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/Montage/1` Components/5 Loading/Skeleton.swift around lines 222 -
226, The line count calculation in Skeleton’s layout logic should not round up,
because `round` can produce an extra line and make the skeleton taller than its
container. Update the `effectiveLineCount` computation in the sizing path that
uses `proxy.size.height` and `scaledLineHeight` to use `floor` instead of
`round`, while keeping the `kind.lineNumber` override and the `max(1, ...)`
minimum intact.
Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift-143-199 (1)

143-199: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

autoComplete 토글이 현재 제안 상태를 즉시 반영하지 않습니다.

제안 계산이 text 변경에만 묶여 있어서, 이미 제안이 떠 있는 상태에서 Line 214의 토글을 끄면 autoCompletionDataSource가 남고, 반대로 non-empty 텍스트에서 켜도 바로 다시 계산되지 않습니다. usingSuggestions 변경에도 datasource를 nil/재계산하도록 동기화해야 옵션과 화면이 맞습니다.

Also applies to: 213-219

🤖 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/TextFieldPreview.swift` around lines
143 - 199, The suggestion datasource is only refreshed from the text change
handler, so toggling usingSuggestions does not immediately clear or rebuild
autoCompletionDataSource. Update the TextFieldPreview logic around the
.onChange(of: text) flow to also observe usingSuggestions and synchronize the
datasource whenever the toggle changes, clearing it when disabled and
recalculating it when enabled with non-empty text. Use the existing
autoCompletionDataSource, usingSuggestions, and candidates logic so the preview
state always matches the toggle.
Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift-13-18 (1)

13-18: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

변경된 @Stateprivate로 제한해 주세요.

이 상태들은 뷰 내부 구현 세부사항인데 현재 private_swiftui_state 경고가 나고 있습니다. 외부 노출을 막아두는 쪽이 맞습니다.

제안된 수정
-    `@State` var typeOption: TypeOption = .circular
+    `@State` private var typeOption: TypeOption = .circular
     // .clear이면 기본 색(circular spinner 기본 색)을 쓴다.
-    `@State` var color: SwiftUI.Color = .clear
+    `@State` private var color: SwiftUI.Color = .clear
     // .clear이면 dimmer를 적용하지 않는다.
-    `@State` var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
-    `@State` var timeout: TimeInterval = 3
+    `@State` private var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
+    `@State` private var timeout: TimeInterval = 3
🤖 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/LoadingPreview.swift` around lines
13 - 18, The LoadingPreview state properties are internal view implementation
details but are currently publicly exposed, triggering the private_swiftui_state
warning. Update the `@State` properties in LoadingPreview to be private, keeping
the existing behavior unchanged while limiting access to typeOption, color,
dimmerColor, and timeout.

Source: Linters/SAST tools

Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift-30-33 (1)

30-33: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

totalPages를 줄일 때 selectedPage도 같이 보정해 주세요.

지금은 selectedPage = 5인 상태에서 totalPages를 1로 낮추면 PageCounter가 범위를 벗어난 상태로 렌더링됩니다. 같은 프리뷰 스택의 다른 파일처럼 setter에서 현재 페이지를 clamp해 두는 편이 안전합니다.

제안 코드
             SliderOptionRow("totalPages", value: Binding(
                 get: { Double(totalPages) },
-                set: { totalPages = Int($0) }
+                set: {
+                    totalPages = Int($0)
+                    selectedPage = min(selectedPage, totalPages)
+                }
             ), in: 1...10, step: 1)
🤖 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/PageCounterPreview.swift` around
lines 30 - 33, The totalPages slider binding in PageCounterPreview only updates
totalPages, so selectedPage can remain out of range when the page count is
reduced. Update the setter in the SliderOptionRow binding to clamp selectedPage
whenever totalPages changes, using the same preview-state pattern already used
elsewhere in the PageCounter preview stack. Keep the fix localized to
PageCounterPreview and make sure selectedPage never exceeds the new totalPages
value.
Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift-123-134 (1)

123-134: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

search variant에서는 trailing 옵션을 그대로 노출하면 상태가 어긋납니다.

일반 variant에서 아이콘/텍스트 trailing을 추가한 뒤 search로 바꾸면, 현재 코드는 focused가 다시 바뀌기 전까지 이전 trailing 구성이 남습니다. search에서는 이 옵션을 숨기거나, variant 전환 시 [.text] / []로 즉시 정규화하는 쪽이 맞습니다.

제안 코드
-                HStack {
-                    Text("trailingContents")
-                    Button(variant: .outlined, size: .small, text: "TextButton") {
-                        trailing.append(.text)
-                    }
-                    Button(variant: .outlined, size: .small, text: "IconButton") {
-                        trailing.append(.icon)
-                    }
-                    IconButton(variant: .outlined(size: .small), icon: .reset) {
-                        trailing = []
-                    }
-                }
+                if !isSearchVariant {
+                    HStack {
+                        Text("trailingContents")
+                        Button(variant: .outlined, size: .small, text: "TextButton") {
+                            trailing.append(.text)
+                        }
+                        Button(variant: .outlined, size: .small, text: "IconButton") {
+                            trailing.append(.icon)
+                        }
+                        IconButton(variant: .outlined(size: .small), icon: .reset) {
+                            trailing = []
+                        }
+                    }
+                }
🤖 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/TopNavigationPreview.swift` around
lines 123 - 134, The trailing controls in TopNavigationPreview keep stale state
when switching to the search variant, so update the preview state handling
around the trailing HStack and variant toggles to hide trailing options for
search or immediately normalize trailing when variant changes. Use the existing
TopNavigationPreview state symbols such as trailing, focused, and the variant
switch logic to ensure search always resets to the correct trailing
configuration instead of preserving prior text/icon selections.
documentation/utilities/ios-utility-components/typography.md-223-226 (1)

223-226: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

uiTextStyle 설명 문장이 어색하게 끊겨 있습니다.

Line 226의 과 동일한 논리이며는 앞 대상이 빠져 의미가 모호합니다. textStyle과 동일한 논리이며처럼 주어를 넣어 문장을 완결해 주세요.

🤖 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 `@documentation/utilities/ios-utility-components/typography.md` around lines
223 - 226, `uiTextStyle` 설명 문장이 주어 없이 끊겨 있어 의미가 모호합니다. `typography.md`의
`uiTextStyle` 항목 설명을 다듬어, `textStyle`을 명시적으로 앞에 두는 형태로 문장을 완결하세요. 이 설명은 Dynamic
Type 기준과 UIKit 케이스 이름 차이를 함께 전달해야 하므로, `uiTextStyle` 서술문 전체를 자연스럽게 이어지도록 수정하면
됩니다.
packages/montage-mcp/data/components.json-1033-1036 (1)

1033-1036: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

interactionColor(_:) 설명 문자열이 깨져 있습니다.

기본값: 뒤가 비어 있어서 생성 문서에 그대로 노출되면 설명이 어색합니다. 실제 기본값을 채우거나, 모르면 괄호 구문 자체를 제거하는 편이 낫습니다.

✏️ 제안 수정
-          "summary": "hover / press 시 인터랙션 영역에 사용할 색상을 설정합니다(기본값: ).",
+          "summary": "hover / press 시 인터랙션 영역에 사용할 색상을 설정합니다.",
🤖 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 `@packages/montage-mcp/data/components.json` around lines 1033 - 1036, The
documentation summary for interactionColor(_:) is malformed because the default
value text is empty, so update the summary in components.json to either include
the actual default Color.Semantic value used by the IconButton API or remove the
"(기본값: ...)" fragment entirely if no default should be advertised. Keep the
wording in sync with the interactionColor(Color.Semantic) method so generated
docs render cleanly.
Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift-104-110 (1)

104-110: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

iconOnly 모드에서는 fillWidth 토글을 숨겨 주세요.

현재 아이콘 전용 분기에서는 .fillWidth(...)를 적용하지 않아서, 이 토글이 켜져도 미리보기에 아무 변화가 없습니다. 옵션이 동작하지 않는 상태라 프리뷰가 오해를 줍니다.

🩹 제안 수정
             HStack {
                 if !iconOnly {
                     ToggleOption("leadingIcon", isOn: $leadingIcon)
                     ToggleOption("trailingIcon", isOn: $trailingIcon)
+                    ToggleOption("fillWidth", isOn: $fillWidth)
                 }
-                ToggleOption("fillWidth", isOn: $fillWidth)
             }
🤖 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/ButtonPreview.swift` around lines
104 - 110, `ButtonPreview`의 옵션 UI에서 `iconOnly`일 때도 `fillWidth` 토글이 보이는 문제가 있습니다.
`ButtonPreview`의 토글 구성(HStack)에서 `iconOnly` 분기와 함께 `fillWidth`도 조건부로 숨기도록 수정해,
아이콘 전용 미리보기에서는 동작하지 않는 옵션이 표시되지 않게 하세요. `ToggleOption("fillWidth", isOn:
$fillWidth)`와 `iconOnly` 상태를 함께 사용하는 부분을 기준으로 위치를 찾으면 됩니다.
Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift-55-57 (1)

55-57: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

숫자 슬라이더가 값을 한 단계 낮게 확정할 수 있습니다.

Int(number)는 반올림이 아니라 버림이라서, 드래그가 9.9처럼 끝나면 편집 종료 후 9로 고정됩니다. 이 옵션은 step: 1로 제한하거나 rounded()를 써야 배지 숫자와 조작감이 맞습니다.

🩹 제안 수정
-                SliderOptionRow("number", value: $number, in: 1...110, onEditingEnded: {
-                    number = Double(Int(number))
-                })
+                SliderOptionRow("number", value: $number, in: 1...110, step: 1)
🤖 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/PushBadgePreview.swift` around lines
55 - 57, The number slider in PushBadgePreview’s SliderOptionRow is truncating
the value on edit end because Int(number) floors instead of rounds, so a value
like 9.9 can be fixed as 9. Update the onEditingEnded handling to preserve the
intended whole-number behavior by using rounding or by constraining the control
to whole-number steps (for example, via the SliderOptionRow configuration around
the "number" binding and number assignment).
Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift-66-76 (1)

66-76: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Adjust zIndex를 숨길 때 상태도 같이 정리해 주세요.

always 모드에서 이 토글을 꺼둔 뒤 click 모드로 바꾸면, 옵션은 사라지지만 adjustZIndex == false는 그대로 남아서 click 모드 프리뷰도 낮은 zIndex 설정으로 렌더링됩니다. 모드가 always가 아닐 때는 상태를 true로 되돌리거나, 실제 적용 조건을 modeIndex == 1 && adjustZIndex로 묶는 편이 안전합니다.

🔧 제안 수정안
-            SegmentedIndexRow("Mode", index: $modeIndex, labels: ["click", "always"])
+            SegmentedIndexRow("Mode", index: $modeIndex, labels: ["click", "always"]) { index in
+                if index == 0 {
+                    adjustZIndex = true
+                }
+            }
🤖 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/TooltipPreview.swift` around lines
66 - 76, The `Adjust zIndex` option in `TooltipPreview` is only shown in
`modeIndex == 1`, but its `adjustZIndex` state can stay false after switching
back to click mode and keep affecting the preview. Update the `TooltipPreview`
mode handling so the hidden option is reset when the mode changes away from
always, or gate the actual zIndex behavior with both `modeIndex == 1` and
`adjustZIndex`. Keep the fix localized around the `HStack`/`ToggleOption("Adjust
zIndex", ...)` logic and the `modeIndex` state flow.
Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift-63-63 (1)

63-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

원격 이미지 모드에서 item count가 실제 표시 개수와 어긋납니다.

지금은 슬라이더가 10까지 올라가지만, 같은 파일의 imageUrlsallUrls.count(5개)까지만 반환해서 useLocalImage == false일 때는 6 이상을 선택해도 프리뷰가 더 늘어나지 않습니다. 옵션 값과 실제 렌더링 결과가 달라서 프리뷰 해석이 헷갈립니다.

🔧 제안 수정안
-            SliderOptionRow("item count", value: $itemCount, in: 1...10)
+            SliderOptionRow(
+                "item count",
+                value: $itemCount,
+                in: CGFloat(1)...CGFloat(useLocalImage ? 10 : allUrls.count)
+            )
🤖 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/AvatarGroupPreview.swift` at line
63, `AvatarGroupPreview`의 `item count` 슬라이더 범위가 원격 이미지 모드의 실제 표시 개수와 맞지 않습니다.
`SliderOptionRow`에서 `itemCount`의 상한을 `imageUrls`가 반환하는 실제 원격 URL 개수와 동일하게 맞추거나,
`imageUrls`/렌더링 로직이 `useLocalImage` 값에 따라 같은 기준을 쓰도록 조정하세요. 특히 `imageUrls`,
`itemCount`, `useLocalImage`, `SliderOptionRow`를 함께 확인해 옵션 값과 프리뷰 결과가 일치하게 만드세요.
Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift-61-71 (1)

61-71: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

usesTemplate 토글 라벨을 분리하세요.

두 아이콘을 모두 켜면 옵션 패널에 usesTemplate 토글이 두 개 생겨서 어떤 아이콘을 제어하는지 구분되지 않습니다. VoiceOver와 UI 테스트에서도 식별이 모호해집니다.

🔧 제안 수정
             HStack {
                 ToggleOption("leadingIcon", isOn: $leadingIcon)
                 if leadingIcon {
-                    ToggleOption("usesTemplate", isOn: $leadingIconUsesTemplate)
+                    ToggleOption("leading usesTemplate", isOn: $leadingIconUsesTemplate)
                 }
             }
             HStack {
                 ToggleOption("trailingIcon", isOn: $trailingIcon)
                 if trailingIcon {
-                    ToggleOption("usesTemplate", isOn: $trailingIconUsesTemplate)
+                    ToggleOption("trailing usesTemplate", isOn: $trailingIconUsesTemplate)
                 }
             }

As per path instructions, "VoiceOver 지원 - 적절한 accessibilityLabel과 accessibilityHint 제공".

🤖 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/ContentBadgePreview.swift` around
lines 61 - 71, The `usesTemplate` toggle in `ContentBadgePreview` is duplicated
for both `leadingIcon` and `trailingIcon`, so the labels are ambiguous. Update
the `ToggleOption` calls inside the two `HStack` blocks to use distinct labels
that identify whether they control the leading or trailing icon, and add the
appropriate accessibility label/hint so VoiceOver and UI tests can tell them
apart.

Source: Path instructions

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

37-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

옵션 노출 조건을 표시 문자열에 의존하지 마세요.

isStrongOrNeutralselectableTitle의 prefix로 분기해서, 제목 문구를 바꾸거나 현지화하면 caption 토글 노출 조건도 같이 깨집니다. 여기서는 표시용 문자열이 아니라 VariantKind case 자체를 기준으로 판별하는 편이 안전합니다.

제안된 수정
     var isStrongOrNeutral: Bool {
-        selectableTitle.starts(with: "Strong") ||
-        selectableTitle.starts(with: "Neutral") ||
-        selectableTitle.starts(with: "Custom")
+        switch self {
+        case .strongOne, .strongTwo, .strongAll,
+             .neutralOne, .neutralTwo, .neutralAll,
+             .custom:
+            true
+        case .cancel:
+            false
+        }
     }
🤖 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/ActionAreaPreview.swift` around
lines 37 - 40, `isStrongOrNeutral` is currently using `selectableTitle` string
prefixes to decide caption toggle visibility, which makes the logic fragile when
titles change or are localized. Update the `ActionAreaPreview` logic to derive
this condition from the underlying `VariantKind` case instead of the display
text, and keep `selectableTitle` only for presentation. Use the existing
`VariantKind`-based flow around `isStrongOrNeutral` to locate the change.
Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift (1)

36-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

@Stateprivate로 닫아두는 편이 좋겠습니다.

이 상태값들은 파일 외부에서 접근할 이유가 없어 보입니다. SwiftLint도 Line 36-40을 같은 규칙으로 경고하고 있습니다.

제안 코드
-    `@State` var variantIndex: Int = 0
-    `@State` var leading = false
-    `@State` var trailing: [TrailingButton] = []
-    `@State` var toast: Toast.Model?
-    `@State` var backgroundColor: SwiftUI.Color = .clear
+    `@State` private var variantIndex: Int = 0
+    `@State` private var leading = false
+    `@State` private var trailing: [TrailingButton] = []
+    `@State` private var toast: Toast.Model?
+    `@State` private var backgroundColor: SwiftUI.Color = .clear
🤖 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/TopNavigationPreview.swift` around
lines 36 - 40, The preview state properties in TopNavigationPreview should be
private. Update the `@State` declarations for variantIndex, leading, trailing,
toast, and backgroundColor to use private access so these internal preview-only
values are not exposed outside the view and satisfy the SwiftLint rule.

Source: Linters/SAST tools

Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift (1)

119-137: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

강제 언래핑 대신 옵셔널 바인딩으로 바꿔 주세요.

nil 체크 바로 뒤에서 iconColor!/backgroundColor!/borderColor!를 다시 꺼내고 있어서, 조건식이 바뀌면 즉시 크래시 경로가 됩니다. if let으로 같은 동작을 더 안전하게 표현하는 편이 낫습니다.

♻️ 제안 수정
             .modifying {
-                if iconColor != nil {
-                    $0.iconColor(iconColor!)
+                if let iconColor {
+                    $0.iconColor(iconColor)
                 } else {
                     $0
                 }
             }
             .modifying {
-                if isOutlinedOrSolid && backgroundColor != nil {
-                    $0.backgroundColor(backgroundColor!)
+                if isOutlinedOrSolid, let backgroundColor {
+                    $0.backgroundColor(backgroundColor)
                 } else {
                     $0
                 }
             }
             .modifying {
-                if isOutlined && borderColor != nil {
-                    $0.borderColor(borderColor!)
+                if isOutlined, let borderColor {
+                    $0.borderColor(borderColor)
                 } else {
                     $0
                 }
             }

As per path instructions, **/*.swift: 옵셔널 처리: force unwrapping (!) 사용 최소화, guard 문 활용.

🤖 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 119 - 137, `IconButtonPreview`의 `.modifying` 체인에서 `iconColor!`,
`backgroundColor!`, `borderColor!`를 강제 언래핑하고 있어 안전하지 않습니다. 각 조건문을 `if let` 옵셔널
바인딩으로 바꿔서, `iconColor`, `backgroundColor`, `borderColor`가 존재할 때만
`iconColor(...)`, `backgroundColor(...)`, `borderColor(...)`를 호출하도록 수정해 주세요.
`isOutlinedOrSolid`와 `isOutlined` 분기 로직은 유지하되, `modifying` 블록 내부에서 옵셔널을 직접 꺼내지
않도록 정리하면 됩니다.

Source: Path instructions

🤖 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/FlowLayoutPreview.swift`:
- Around line 17-31: `PreviewLayout` inside `FlowLayoutPreview` currently wraps
the content in an extra `ScrollView`, which causes nested vertical scrolling and
gesture conflicts. Remove the inner `ScrollView` and keep the `ZStack` and
`FlowLayout` content directly inside `PreviewLayout` so the preview uses only
the outer scrolling behavior. Use `PreviewLayout` and `FlowLayout` as the key
spots to update.

In `@Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift`:
- Around line 53-56: The LoadingPreview timeout logic in onChange(of: isLoading)
is using uncancelled asyncAfter callbacks and toggle(), so older timers can
mutate a newer loading cycle. Update the loading timeout handling to keep a
cancellable reference or token for each cycle, cancel any previous pending
timeout when isLoading changes, and only clear the matching loading session
instead of toggling the current value. Use the onChange(of: isLoading) block and
the timeout callback around isLoading to locate the fix.

In `@Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift`:
- Around line 45-50: The `PullToRefreshPreview` refresh-time input currently
accepts arbitrary text, which can allow negative or non-numeric values that
later break the `Task.sleep` path when converting `seconds` to `UInt64`. Update
the `TextField` bound to `seconds` in this preview to restrict input to numeric,
non-negative values only, and add validation/sanitization at the point where the
value is edited so invalid values cannot be entered or persisted. Keep the fix
focused around the `seconds` state and the preview UI that exposes it.

In `@Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift`:
- Around line 46-50: The count change handler in TabPreview’s onChange(of:
count) rebuilds items but leaves selectedIndex unchanged, so shrinking the tab
count can leave the selection out of bounds. After regenerating items, clamp
selectedIndex to the last valid index for the new items array, or reset it to 0
when the previous selection is no longer valid, using the existing selectedIndex
state in TabPreview.

In
`@Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift`:
- Around line 75-76: The progress range in VerticalProgressTrackerPreview is too
wide for the available stepContents and can produce an invalid progress state.
Update the PrevNextOptionRow binding in the preview so the allowed range matches
the actual number of steps defined by stepContents, preventing progress from
reaching a non-existent step and avoiding incorrect rendering or asserts.

In `@Sources/Blueprint/Sources/Utilities/PreviewLayout.swift`:
- Around line 100-101: The new hasOptions check in PreviewLayout should be
applied consistently across the .upsideDown and .floating rendering branches,
not just the main layout path. Update the PreviewLayout body so the “Options”
header and its panel are conditionally omitted whenever Options.self is
EmptyView, reusing hasOptions in the affected branches and preserving the
existing behavior for non-empty options.
- Around line 256-260: 아이콘만 있는 버튼에 VoiceOver용 접근성 정보가 빠져 있습니다. PreviewLayout의
showChecker를 토글하는 Button과 함께 동일 파일의 뒤로가기 버튼에도 accessibilityLabel과
accessibilityHint를 추가해, SF Symbol만 보이더라도 의미 있는 이름으로 읽히도록 수정하세요. 버튼의 label 역할을 하는
Image(systemName:)는 유지하되, 각 버튼이 무엇을 하는지 명확히 드러나게 접근성 속성을 보강하면 됩니다.

In `@Sources/Blueprint/Sources/Utilities/PreviewOption.swift`:
- Around line 46-60: The option row controls currently render the title
separately from the interactive control, so the SegmentedControl and similar
inputs end up without an accessible label. Update PreviewOption’s body so the
actual control receives the row title as its accessibility label, or combine the
row into a single accessibility element; apply the same pattern to the other
affected option-row views referenced in this change so each interactive control
exposes a meaningful VoiceOver label and hint.

In `@Sources/Montage/1` Components/2 Actions/IconButton.swift:
- Around line 262-305: The public Variant API in IconButton has a breaking
signature change because normal, outlined, and solid now use different
associated value types, which will break existing callers. Keep the current
Int-based path compatible by preserving the old Variant cases or adding a
deprecated compatibility layer in IconButton.Variant, and migrate internal call
sites like Category, Tab, SnackBar, Popover, and Card to the new shape only if
this is a major-version change. If this release is non-major, mark the old API
deprecated with `@available` and avoid removing the existing contract.

In `@Sources/Montage/1` Components/3 Selection And Input/TextArea.swift:
- Around line 124-133: 아이콘-only segmentedControl은 현재 각 항목의 의미와 상태를 VoiceOver가
구분할 수 없으므로, `TextArea.Segment`의
`segmentedControl(selectedIndex:icons:onSelect:)`와 해당 렌더링 로직에서 접근성 정보를 추가하도록
수정하세요. `icons: [Icon]`만으로는 부족하니 각 세그먼트에 `accessibilityLabel`과
`accessibilityHint`를 전달할 수 있는 구조를 보완하고, `Image` + `onTapGesture` 대신 버튼 의미론이
유지되도록 `segmentedControl`/세그먼트 뷰의 접근성 설정을 적용하세요.

In `@Sources/Montage/1` Components/3 Selection And Input/TextField.swift:
- Around line 162-170: The public backgroundColor(_:) modifier is currently a
no-op because it only sets customBackgroundColor and the new fieldBackground
path never reads that value. Update TextField’s background rendering logic to
consume customBackgroundColor when building the field background, and ensure the
modifier still overrides the default background in the main TextField view path
and any related background helper used by the refactor.
- Around line 372-382: The TextField accessibility setup is overriding the real
input value with a status string, so VoiceOver cannot read what the user typed.
Update TextField.swift in the TextField view to stop using accessibilityValue
for the error/empty state alone; instead keep the actual text exposed and move
the status into accessibilityHint or accessibilityLabel, or combine the status
with the current text in accessibilityValue. Apply the same fix in the other
matching TextField accessibility block referenced by the review so both paths
preserve the typed value.

---

Outside diff comments:
In `@Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift`:
- Around line 27-45: When the selected color type changes to .atomic in
ColorPreview, the transparent checker state must be reset as well. Update the
selection handling around selectedColorTypeIndex so that switching to the atomic
case also sets showTransparentChecker to false, instead of only disabling the
checkerboard Button. Use the existing ColorPreview, selectedColorTypeIndex,
showTransparentChecker, and ColorType.allCases references to locate the logic
and keep the preview state aligned with the active segment.

---

Minor comments:
In `@documentation/utilities/ios-utility-components/typography.md`:
- Around line 223-226: `uiTextStyle` 설명 문장이 주어 없이 끊겨 있어 의미가 모호합니다.
`typography.md`의 `uiTextStyle` 항목 설명을 다듬어, `textStyle`을 명시적으로 앞에 두는 형태로 문장을
완결하세요. 이 설명은 Dynamic Type 기준과 UIKit 케이스 이름 차이를 함께 전달해야 하므로, `uiTextStyle` 서술문
전체를 자연스럽게 이어지도록 수정하면 됩니다.

In `@packages/montage-mcp/data/components.json`:
- Around line 1033-1036: The documentation summary for interactionColor(_:) is
malformed because the default value text is empty, so update the summary in
components.json to either include the actual default Color.Semantic value used
by the IconButton API or remove the "(기본값: ...)" fragment entirely if no default
should be advertised. Keep the wording in sync with the
interactionColor(Color.Semantic) method so generated docs render cleanly.

In `@Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift`:
- Line 63: `AvatarGroupPreview`의 `item count` 슬라이더 범위가 원격 이미지 모드의 실제 표시 개수와 맞지
않습니다. `SliderOptionRow`에서 `itemCount`의 상한을 `imageUrls`가 반환하는 실제 원격 URL 개수와 동일하게
맞추거나, `imageUrls`/렌더링 로직이 `useLocalImage` 값에 따라 같은 기준을 쓰도록 조정하세요. 특히
`imageUrls`, `itemCount`, `useLocalImage`, `SliderOptionRow`를 함께 확인해 옵션 값과 프리뷰
결과가 일치하게 만드세요.

In `@Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift`:
- Around line 104-110: `ButtonPreview`의 옵션 UI에서 `iconOnly`일 때도 `fillWidth` 토글이
보이는 문제가 있습니다. `ButtonPreview`의 토글 구성(HStack)에서 `iconOnly` 분기와 함께 `fillWidth`도
조건부로 숨기도록 수정해, 아이콘 전용 미리보기에서는 동작하지 않는 옵션이 표시되지 않게 하세요.
`ToggleOption("fillWidth", isOn: $fillWidth)`와 `iconOnly` 상태를 함께 사용하는 부분을 기준으로
위치를 찾으면 됩니다.

In `@Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift`:
- Around line 61-71: The `usesTemplate` toggle in `ContentBadgePreview` is
duplicated for both `leadingIcon` and `trailingIcon`, so the labels are
ambiguous. Update the `ToggleOption` calls inside the two `HStack` blocks to use
distinct labels that identify whether they control the leading or trailing icon,
and add the appropriate accessibility label/hint so VoiceOver and UI tests can
tell them apart.

In `@Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift`:
- Around line 13-18: The LoadingPreview state properties are internal view
implementation details but are currently publicly exposed, triggering the
private_swiftui_state warning. Update the `@State` properties in LoadingPreview to
be private, keeping the existing behavior unchanged while limiting access to
typeOption, color, dimmerColor, and timeout.

In `@Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift`:
- Around line 30-33: The totalPages slider binding in PageCounterPreview only
updates totalPages, so selectedPage can remain out of range when the page count
is reduced. Update the setter in the SliderOptionRow binding to clamp
selectedPage whenever totalPages changes, using the same preview-state pattern
already used elsewhere in the PageCounter preview stack. Keep the fix localized
to PageCounterPreview and make sure selectedPage never exceeds the new
totalPages value.

In `@Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift`:
- Around line 55-57: The number slider in PushBadgePreview’s SliderOptionRow is
truncating the value on edit end because Int(number) floors instead of rounds,
so a value like 9.9 can be fixed as 9. Update the onEditingEnded handling to
preserve the intended whole-number behavior by using rounding or by constraining
the control to whole-number steps (for example, via the SliderOptionRow
configuration around the "number" binding and number assignment).

In `@Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift`:
- Around line 143-199: The suggestion datasource is only refreshed from the text
change handler, so toggling usingSuggestions does not immediately clear or
rebuild autoCompletionDataSource. Update the TextFieldPreview logic around the
.onChange(of: text) flow to also observe usingSuggestions and synchronize the
datasource whenever the toggle changes, clearing it when disabled and
recalculating it when enabled with non-empty text. Use the existing
autoCompletionDataSource, usingSuggestions, and candidates logic so the preview
state always matches the toggle.

In `@Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift`:
- Around line 66-76: The `Adjust zIndex` option in `TooltipPreview` is only
shown in `modeIndex == 1`, but its `adjustZIndex` state can stay false after
switching back to click mode and keep affecting the preview. Update the
`TooltipPreview` mode handling so the hidden option is reset when the mode
changes away from always, or gate the actual zIndex behavior with both
`modeIndex == 1` and `adjustZIndex`. Keep the fix localized around the
`HStack`/`ToggleOption("Adjust zIndex", ...)` logic and the `modeIndex` state
flow.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 123-134: The trailing controls in TopNavigationPreview keep stale
state when switching to the search variant, so update the preview state handling
around the trailing HStack and variant toggles to hide trailing options for
search or immediately normalize trailing when variant changes. Use the existing
TopNavigationPreview state symbols such as trailing, focused, and the variant
switch logic to ensure search always resets to the correct trailing
configuration instead of preserving prior text/icon selections.

In `@Sources/Montage/1` Components/5 Loading/Skeleton.swift:
- Around line 222-226: The line count calculation in Skeleton’s layout logic
should not round up, because `round` can produce an extra line and make the
skeleton taller than its container. Update the `effectiveLineCount` computation
in the sizing path that uses `proxy.size.height` and `scaledLineHeight` to use
`floor` instead of `round`, while keeping the `kind.lineNumber` override and the
`max(1, ...)` minimum intact.

---

Nitpick comments:
In `@Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift`:
- Around line 37-40: `isStrongOrNeutral` is currently using `selectableTitle`
string prefixes to decide caption toggle visibility, which makes the logic
fragile when titles change or are localized. Update the `ActionAreaPreview`
logic to derive this condition from the underlying `VariantKind` case instead of
the display text, and keep `selectableTitle` only for presentation. Use the
existing `VariantKind`-based flow around `isStrongOrNeutral` to locate the
change.

In `@Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift`:
- Around line 119-137: `IconButtonPreview`의 `.modifying` 체인에서 `iconColor!`,
`backgroundColor!`, `borderColor!`를 강제 언래핑하고 있어 안전하지 않습니다. 각 조건문을 `if let` 옵셔널
바인딩으로 바꿔서, `iconColor`, `backgroundColor`, `borderColor`가 존재할 때만
`iconColor(...)`, `backgroundColor(...)`, `borderColor(...)`를 호출하도록 수정해 주세요.
`isOutlinedOrSolid`와 `isOutlined` 분기 로직은 유지하되, `modifying` 블록 내부에서 옵셔널을 직접 꺼내지
않도록 정리하면 됩니다.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 36-40: The preview state properties in TopNavigationPreview should
be private. Update the `@State` declarations for variantIndex, leading, trailing,
toast, and backgroundColor to use private access so these internal preview-only
values are not exposed outside the view and satisfy the SwiftLint rule.
🪄 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: 6dfd73f0-5192-4332-ad2e-c59634618b97

📥 Commits

Reviewing files that changed from the base of the PR and between 5b9ea73 and 76d7ed6.

📒 Files selected for processing (113)
  • .gitignore
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListView.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TypographyPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Montage/1 Components/2 Actions/Button.swift
  • Sources/Montage/1 Components/2 Actions/IconButton.swift
  • Sources/Montage/1 Components/2 Actions/OutlinedUIButton.swift
  • Sources/Montage/1 Components/2 Actions/SolidUIButton.swift
  • Sources/Montage/1 Components/3 Selection And Input/Control.swift
  • Sources/Montage/1 Components/3 Selection And Input/Select.swift
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextField.swift
  • Sources/Montage/1 Components/4 Contents/Accordion.swift
  • Sources/Montage/1 Components/4 Contents/Card.swift
  • Sources/Montage/1 Components/4 Contents/ContentBadgeUIView.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Montage/1 Components/5 Loading/Skeleton.swift
  • Sources/Montage/1 Components/6 Navigations/Category.swift
  • Sources/Montage/1 Components/6 Navigations/Tab.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Montage/1 Components/7 Feedback/SnackBar.swift
  • Sources/Montage/1 Components/8 Presentation/Popover.swift
  • Sources/Montage/1 Components/9 Utilities/Color.swift
  • Sources/Montage/1 Components/9 Utilities/Dimension.swift
  • Sources/Montage/1 Components/9 Utilities/InteractionUIView.swift
  • Sources/Montage/1 Components/9 Utilities/ModalNavigation.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
  • Sources/Montage/1 Components/9 Utilities/Typography.swift
  • Sources/Montage/2 Utilities/Extension/SwiftUI/SwiftUI+Debug.swift
  • Sources/Montage/2 Utilities/Extension/UIKit/NSAttributedString+.swift
  • Sources/Montage/Asset/Color.xcassets/Pink/pink100.colorset/Contents.json
  • Sources/Montage/Asset/Color.xcassets/Violet/violet0.colorset/Contents.json
  • Sources/Montage/Asset/Color.xcassets/Violet/violet100.colorset/Contents.json
  • Sources/Montage/Asset/Localizable.xcstrings
  • documentation/components/actions/button/ios.md
  • documentation/components/actions/iconbutton/ios.md
  • documentation/components/contents/accordion/ios.md
  • documentation/components/loading/skeleton/ios.md
  • documentation/components/selection and input/textarea/ios.md
  • documentation/components/selection and input/textfield/ios.md
  • documentation/utilities/ios-extensions/corefoundation.md
  • documentation/utilities/ios-extensions/swift.md
  • documentation/utilities/ios-utility-components/color.md
  • documentation/utilities/ios-utility-components/dimension.md
  • documentation/utilities/ios-utility-components/modalnavigation.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
  • documentation/utilities/ios-utility-components/typography.md
  • packages/montage-mcp/data/components.json
  • packages/montage-mcp/data/markdown/coding-guidelines.md
  • packages/montage-mcp/data/markdown/color-usage.md
  • packages/montage-mcp/data/tokens.json
  • scripts/build_mcp_data.js
💤 Files with no reviewable changes (11)
  • documentation/components/contents/accordion/ios.md
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • documentation/utilities/ios-extensions/swift.md
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Montage/1 Components/2 Actions/SolidUIButton.swift
  • documentation/components/loading/skeleton/ios.md
  • Sources/Montage/1 Components/4 Contents/ContentBadgeUIView.swift
  • Sources/Montage/1 Components/4 Contents/Accordion.swift
  • documentation/utilities/ios-utility-components/modalnavigation.md
  • Sources/Montage/1 Components/2 Actions/OutlinedUIButton.swift
  • Sources/Montage/1 Components/9 Utilities/InteractionUIView.swift

Comment thread Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
Comment thread Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift
Comment thread Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
Comment thread Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
Comment thread Sources/Blueprint/Sources/Utilities/PreviewOption.swift
Comment thread Sources/Montage/1 Components/2 Actions/IconButton.swift
Comment thread Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
Comment thread Sources/Montage/1 Components/3 Selection And Input/TextField.swift
Comment thread Sources/Montage/1 Components/3 Selection And Input/TextField.swift Outdated
@github-actions github-actions Bot added the in review This issue requires a review. label Jun 26, 2026
@knine79 knine79 changed the base branch from main to release/4.0.0 June 29, 2026 03:36
@knine79

knine79 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai 타겟이 잘못 설정되어 있었어 리뷰 처음부터 다시 해줘

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

@knine79 알겠습니다. 타겟 설정이 잘못되었던 점 반영해서 이번 PR 전체를 처음부터 다시 검토하겠습니다.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift (1)

27-52: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Atomic으로 바꿔도 체커 상태가 남습니다.

여기서는 토글만 비활성화하고 showTransparentChecker 값은 그대로 유지해서, semantic/all에서 체커를 켠 뒤 atomic으로 전환하면 AtomicColorSections(showTransparentChecker: showTransparentChecker)가 계속 true를 받습니다. atomic 선택 시 값을 false로 리셋하거나, atomic 분기에는 항상 false를 넘겨서 상태를 같이 정리해 주세요.

🤖 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/ColorPreview.swift` around lines 27
- 52, `ColorPreview`의 `showTransparentChecker` 상태가 atomic 선택 시에도 유지되어
`AtomicColorSections`에 true가 전달되는 문제가 있습니다. `selectedColorTypeIndex`를 기준으로 분기하는
`Button`/`ScrollView` 흐름에서 atomic로 전환될 때 `showTransparentChecker`를 false로 리셋하거나,
`AtomicColorSections(showTransparentChecker:)`에는 항상 false를 넘기도록 수정해 상태가 섞이지 않게
정리하세요.
Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift (1)

169-174: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

resize를 바꾸면 현재 입력값이 지워집니다.

높이 갱신용 workaround가 text를 강제로 " """로 바꿔서, 사용자가 입력한 내용을 resize 전환마다 잃게 만듭니다. 프리뷰 상태를 유지한 채 레이아웃만 새로 고치도록 TextArea에 별도 refresh key를 주거나 .id(resize) 같은 방식으로 분리하는 편이 안전합니다.

🤖 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/TextAreaPreview.swift` around lines
169 - 174, The resize workaround in TextAreaPreview is mutating the bound text
value, which clears the user’s input whenever resize changes. Update the
.onChange(of: resize) handling in TextAreaPreview to refresh the layout without
changing text, and use a separate refresh trigger for TextArea such as a
dedicated refresh key or an .id(resize)-style split so the preview state stays
intact while only the layout is re-rendered.
🧹 Nitpick comments (1)
Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift (1)

119-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

강제 언래핑을 없애는 편이 안전합니다.

iconColor!, backgroundColor!, borderColor!는 지금은 앞선 분기에 기대고 있지만, 조건식이 조금만 바뀌어도 바로 크래시 포인트가 됩니다. if let iconColor, if let backgroundColor, if let borderColor처럼 지역 바인딩으로 바꾸면 같은 동작을 더 안전하게 유지할 수 있습니다. As per path instructions, "옵셔널 처리: force unwrapping (!) 사용 최소화".

제안된 수정
             .modifying {
-                if iconColor != nil {
-                    $0.iconColor(iconColor!)
+                if let iconColor {
+                    $0.iconColor(iconColor)
                 } else {
                     $0
                 }
             }
             .modifying {
-                if isOutlinedOrSolid && backgroundColor != nil {
-                    $0.backgroundColor(backgroundColor!)
+                if isOutlinedOrSolid, let backgroundColor {
+                    $0.backgroundColor(backgroundColor)
                 } else {
                     $0
                 }
             }
             .modifying {
-                if isOutlined && borderColor != nil {
-                    $0.borderColor(borderColor!)
+                if isOutlined, let borderColor {
+                    $0.borderColor(borderColor)
                 } else {
                     $0
                 }
             }
🤖 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 119 - 135, In IconButtonPreview’s modifying chain, replace the
force-unwrapped optional uses for iconColor, backgroundColor, and borderColor
with safe local binding. Update each conditional block in the preview builder to
use if let-style unwrapping before calling iconColor(...), backgroundColor(...),
and borderColor(...) so the behavior stays the same without relying on `!`. Keep
the changes scoped to the existing `.modifying` closures in IconButtonPreview.

Source: Path instructions

🤖 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 `@packages/montage-mcp/data/components.json`:
- Around line 2410-2426: `TextArea.Resource`의 MCP 메타데이터에서 public instance
property인 `isLeadingAllowed`가 빠져 있습니다. `components.json`에서 `TextArea.Resource`
항목을 찾아 `cases`와 `staticMethods` 옆에 `instanceProperties`를 추가하고, 그 안에
`isLeadingAllowed`를 노출하도록 맞춰 주세요. 이렇게 하면 Swift 코드와 DocC에 있는 `isLeadingAllowed`
계약이 MCP 메타데이터와 일치합니다.

In `@Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift`:
- Line 63: `AvatarGroupPreview`의 `SliderOptionRow("item count", value:
$itemCount, in: 1...10)`는 연속값을 허용해 실제 렌더링에서 `Int(itemCount)`로 잘리는 값과 불일치가 생깁니다.
`itemCount`가 항상 정수로만 바뀌도록 이 슬라이더에 step 1을 적용하고, 관련 렌더링 로직(아바타 개수를
`Int(itemCount)`로 쓰는 부분)과 값이 일치하도록 유지하세요.

In
`@Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift`:
- Around line 20-24: `HorizontalProgressTrackerPreview`에서 `stepCount`가 바뀔 때
`ProgressTracker`의 `labels`와 `PrevNextOptionRow`의 범위가 잠깐 불일치합니다. `progress`와
`labels`를 함께 관리하는 정규화 지점을 만들어 `stepCount` 변경 시 현재 `progress`를 새 범위에 맞게 보정하고,
`labels`도 같은 시점에 새 개수에 맞춰 갱신한 뒤 `ProgressTracker`와 `PrevNextOptionRow`가 동일한 상태를
보도록 조정하세요.

In `@Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift`:
- Around line 30-33: `PageCounterPreview`의 `SliderOptionRow("totalPages",
value:)` setter는 `totalPages`만 갱신해서 `selectedPage`가 범위를 벗어날 수 있습니다.
`totalPages`를 변경할 때 `selectedPage`도 함께 보정하도록 수정하고,
`PageCounter(selectedPage:totalPages:)`에 항상 유효한 조합이 들어가도록 `selectedPage`를 새
`totalPages` 범위로 클램프하세요.

In `@Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift`:
- Around line 36-44: `PaginationDotsPreview`의 `SliderOptionRow("totalPages",
...)`는 `totalPages`가 Int인데도 정수 step이 없어 드래그 중 연속값이 잘리는 문제가 있습니다. 이 바인딩의 슬라이더 설정을
정수 도메인에 맞게 고정하도록 `step: 1`을 추가하고, `selectedPage`를 `totalPages`로 clamp하는 기존 로직은
그대로 유지하세요.

In `@Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift`:
- Around line 55-57: The PushBadgePreview slider is still allowing continuous
values while the badge logic expects integers, so the displayed option can drift
from the actual value. Update SliderOptionRow in PushBadgePreview so the number
control is constrained to integer steps by using step 1 instead of rounding in
onEditingEnded, and keep the value aligned with the Int-based badge state.

In `@Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift`:
- Around line 77-92: When `customMenu` is turned off, make sure `showSheet` is
also reset so the `.bottomSheet(isPresented: $showSheet)` bound in
`SelectPreview` does not stay open or get reused unexpectedly. Update the
toggle/option handling around `menuPresented` and the `.bottomSheet` binding to
clear `showSheet` whenever the custom menu is disabled, using the existing
`showSheet`, `customMenu`, and `SelectPreview` state flow.

In `@Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift`:
- Around line 129-157: The preview menu in TextAreaPreview is keeping the wrong
slice type and order when updating leadingResources and trailingResources.
Update the resource trimming logic in the MenuOptionRow button actions so the
arrays are reassigned from the first three items, matching bottomResources(...)
and avoiding the ArraySlice mismatch; use the existing leadingResources and
trailingResources handling as the place to fix it.

In `@Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift`:
- Around line 143-219: The autoComplete toggle state is only reflected from the
text change handler, so the suggestion list can become stale when
`usingSuggestions` changes. Update the `TextFieldPreview` logic in the
`onChange(of: text)` flow and add an `onChange(of: usingSuggestions)` handler to
immediately clear `autoCompletionDataSource` when disabled and recompute it from
the current `text` when enabled, keeping the datasource in sync with the toggle.

In `@Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift`:
- Around line 37-39: The ForEach in ThumbnailPreview is using ratio.hashValue as
the identifier, which is not stable and can break SwiftUI diffing. Update the
ForEach over ratios to use a stable identity such as id: \.self for
Thumbnail.Ratio, and keep the Button selection logic unchanged so selectedRatio
still updates correctly.

In `@Sources/Blueprint/Sources/Utilities/PreviewLayout.swift`:
- Around line 408-429: The card-level DragGesture on the preview layout is
intercepting drag input from inner controls like SliderOptionRow and
TextAreaOptionRow. Move the drag handling out of the main card container in
PreviewLayout and attach it only to the handle area (the Capsule/header section)
so floating-mode option controls can receive their own gestures without
competing with card movement.

In `@Sources/Montage/1` Components/3 Selection And Input/TextArea.swift:
- Around line 429-432: The TextArea accessibility setup is overwriting the
field’s accessible value with only an error string or empty string, which can
prevent VoiceOver from reading the actual input text. Update the TextArea
modifier chain near the onTapGesture/accessibilityValue logic so the current
text remains exposed as the accessibilityValue, and move the error state into a
separate accessibilityHint or accessibilityLabel using the relevant TextArea
state such as negative.
- Around line 391-392: The TextAreaView onAppear handler is triggering
onTextChange(text) during the initial render, which violates the “only when
changed” contract. Update the TextArea.swift implementation around the
onAppear/onTextChange flow so the callback is not fired on first display, and
only invoke it from actual text-change handling paths; if this behavior is
intentional, make the contract explicit in the relevant API/documentation.

---

Outside diff comments:
In `@Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift`:
- Around line 27-52: `ColorPreview`의 `showTransparentChecker` 상태가 atomic 선택 시에도
유지되어 `AtomicColorSections`에 true가 전달되는 문제가 있습니다. `selectedColorTypeIndex`를 기준으로
분기하는 `Button`/`ScrollView` 흐름에서 atomic로 전환될 때 `showTransparentChecker`를 false로
리셋하거나, `AtomicColorSections(showTransparentChecker:)`에는 항상 false를 넘기도록 수정해 상태가
섞이지 않게 정리하세요.

In `@Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift`:
- Around line 169-174: The resize workaround in TextAreaPreview is mutating the
bound text value, which clears the user’s input whenever resize changes. Update
the .onChange(of: resize) handling in TextAreaPreview to refresh the layout
without changing text, and use a separate refresh trigger for TextArea such as a
dedicated refresh key or an .id(resize)-style split so the preview state stays
intact while only the layout is re-rendered.

---

Nitpick comments:
In `@Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift`:
- Around line 119-135: In IconButtonPreview’s modifying chain, replace the
force-unwrapped optional uses for iconColor, backgroundColor, and borderColor
with safe local binding. Update each conditional block in the preview builder to
use if let-style unwrapping before calling iconColor(...), backgroundColor(...),
and borderColor(...) so the behavior stays the same without relying on `!`. Keep
the changes scoped to the existing `.modifying` closures in IconButtonPreview.
🪄 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: b03d4b42-36f6-42be-aaac-1c60d9c462c8

📥 Commits

Reviewing files that changed from the base of the PR and between 9322aa7 and 76d7ed6.

📒 Files selected for processing (64)
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextField.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • documentation/components/selection and input/textarea/ios.md
  • documentation/components/selection and input/textfield/ios.md
  • packages/montage-mcp/data/components.json
💤 Files with no reviewable changes (2)
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift

Comment thread packages/montage-mcp/data/components.json
Comment thread Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift Outdated
Comment thread Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
Comment thread Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift Outdated
Comment thread Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift Outdated
Comment thread Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift Outdated
Comment thread Sources/Blueprint/Sources/Utilities/PreviewLayout.swift Outdated
Comment thread Sources/Montage/1 Components/3 Selection And Input/TextArea.swift Outdated
Comment thread Sources/Montage/1 Components/3 Selection And Input/TextArea.swift Outdated
@knine79 knine79 added this to the 4.0.0 milestone Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@scripts/build_mcp_data.js`:
- Around line 175-179: The Instance Properties collection in build_mcp_data.js
is including inherited members such as body and description, so filter
extractMembers output to keep only properties declared on the current symbol.
Update the logic around instanceProps before assigning record.instanceProperties
so entries summarized with “Inherited from” are excluded, while keeping direct
members from the current type only.
🪄 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: c3e15d5d-d77c-4203-bf91-d1da9a9927bb

📥 Commits

Reviewing files that changed from the base of the PR and between 76d7ed6 and 61b2f09.

📒 Files selected for processing (14)
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
  • packages/montage-mcp/data/components.json
  • packages/montage-mcp/data/tokens.json
  • scripts/build_mcp_data.js
🚧 Files skipped from review as they are similar to previous changes (10)
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift

Comment thread scripts/build_mcp_data.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/montage-mcp/data/components.json (1)

2302-2307: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

요약 문자열이 잘려 MCP 설명 계약이 깨졌습니다.

Line 2302와 Line 2522의 summary가 각각 infinity/trailing 전용 리소스 이름을 잃어서 의미가 불완전합니다. 생성기에서 abstractcodeVoice 같은 비-text fragment도 함께 합쳐 재생성해야 합니다.

Also applies to: 2522-2527

🤖 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 `@packages/montage-mcp/data/components.json` around lines 2302 - 2307, The
`summary` text for the affected component entries is being truncated and loses
meaning because non-text fragments are not being merged into the final MCP
description. Update the generator that builds `components.json` so the `summary`
for `rawValue` and the related `abstract` entry preserves all fragments,
including `codeVoice` and other non-text pieces like `infinity`/trailing
resource names, when composing the final string.
🤖 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.

Outside diff comments:
In `@packages/montage-mcp/data/components.json`:
- Around line 2302-2307: The `summary` text for the affected component entries
is being truncated and loses meaning because non-text fragments are not being
merged into the final MCP description. Update the generator that builds
`components.json` so the `summary` for `rawValue` and the related `abstract`
entry preserves all fragments, including `codeVoice` and other non-text pieces
like `infinity`/trailing resource names, when composing the final string.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e3517e5d-4d1c-42d3-ac28-bffdf4e4c4d3

📥 Commits

Reviewing files that changed from the base of the PR and between 61b2f09 and 80c0a86.

📒 Files selected for processing (2)
  • packages/montage-mcp/data/components.json
  • scripts/build_mcp_data.js

@github-actions github-actions Bot added accepted This issue has been reviewed. and removed in review This issue requires a review. labels Jun 29, 2026
@knine79 knine79 changed the base branch from release/4.0.0 to feature/WRP-1247 June 29, 2026 07:54
knine79 and others added 12 commits June 29, 2026 16:56
PreviewLayout(stacked/overlay/pinnedTop)·PreviewOption 행 컴포넌트 신설, 6개 프리뷰 마이그레이션, ProgressTracker·Pagination 분기메뉴 제거 후 자식 프리뷰 직접 노출.

# Conflicts:
#	Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
stacked 다수 + overlay(Toast/Popup/Popover/BottomSheet/Select/DateTimePicker/ActionArea) + pinnedTop(ModalNavigation) 전환. Color/Icon 카탈로그·Loading·Typography는 bespoke 유지.
하단 고정 액션 바가 화면 하단에 floating되도록 .overlay 적용. overlayBody의 끝 Spacer를 제거해 greedy 미리보기가 남은 공간을 채우게 함(Toast/SnackBar는 EmptyView라 영향 없음).
패딩을 옵션 블록에만 적용하고 미리보기는 화면 너비를 채우도록 함. ActionArea 등 전체화면 컴포넌트의 배경·그래디언트·하단 바가 좌우 여백 없이 그려진다.
이미지 로더를 URL로 식별되는 내부 뷰(ThumbnailImageLoader)로 분리하고 .id(urlString) 적용. URL이 바뀌면 ImageManager가 새로 생성돼, 직전 로드의 stale 이미지/에러를 우선 표시하던 회귀(거꾸로/한 박자 지연)를 해결.
PreviewLayout이 미리보기 슬롯을 .frame(maxWidth: .infinity)로 가운데 정렬하고, 개별 프리뷰의 HStack { Spacer … Spacer } 래퍼를 제거.
PreviewLayout에 .floating 모드 신설: 미리보기를 전체화면으로 채우고 체커를 컨테이너가 자동 적용(previewCheckered 불필요), 옵션을 드래그로 옮길 수 있는 floating material 카드(DraggableCard)로 띄움. TopNavigation 프리뷰를 .floating으로 전환해 프로토타입 적용.
Blueprint 프리뷰:
- TextAreaPreview: leading/trailing 리소스 제한을 suffix(3)→Array(prefix(3))로 수정 (타입 불일치·동작 정합)
- 정수 도메인 슬라이더(Avatar/Pagination/PushBadge)에 step:1 명시
- PageCounter: totalPages 축소 시 selectedPage 클램프
- HorizontalProgressTracker: stepCount 변경 시 labels·progress를 함께 정규화해 모델 불일치 제거
- SelectPreview: customMenu 끌 때 열린 bottomSheet 정리
- TextFieldPreview: autoComplete 토글 시 자동완성 즉시 동기화 (helper 분리)
- ThumbnailPreview: ForEach 식별자 hashValue→\.self
- PreviewLayout: floating 옵션 카드 드래그를 핸들에만 적용해 내부 컨트롤과 충돌 방지

Montage:
- TextArea: onTextChange 초기 렌더 호출 제거 (변경 시에만 호출 계약 준수)
- TextArea: 오류 상태를 accessibilityValue 대신 accessibilityHint로 분리해 실제 입력값 노출 유지

MCP 데이터 생성기:
- nested 타입의 Instance Properties를 추출하도록 보완 (TextArea.Resource.isLeadingAllowed 등 누락 해소)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8gTT3K3Hci759WS9qMf8r
이전 커밋에서 nested 타입의 instanceProperties를 추출하면서 프로토콜 상속 멤버
(ModalNavigation.Variant.description, *.body 등)가 'Inherited from .' 요약으로
함께 노출되던 문제를 수정. DocC 상속 마커(abstract가 'Inherited from'으로 시작)를
가진 멤버를 extractMembers에서 건너뛴다.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8gTT3K3Hci759WS9qMf8r
@knine79 knine79 force-pushed the refactor/blueprint-preview-layout branch from 80c0a86 to fc31f89 Compare June 29, 2026 07:57
@github-actions github-actions Bot added in review This issue requires a review. and removed accepted This issue has been reviewed. labels Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

36-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

프리뷰 로컬 @Stateprivate으로 닫아 주세요.

이 값들도 모두 뷰 내부 상태라 공개 범위를 넓힐 필요가 없습니다. 현재 변경분만으로도 SwiftLint 경고가 남습니다.

🔧 제안된 수정
-    `@State` var variantIndex: Int = 0
+    `@State` private var variantIndex: Int = 0
-    `@State` var leading = false
+    `@State` private var leading = false
-    `@State` var trailing: [TrailingButton] = []
+    `@State` private var trailing: [TrailingButton] = []
-    `@State` var toast: Toast.Model?
+    `@State` private var toast: Toast.Model?
-    `@State` var backgroundColor: SwiftUI.Color = .clear
+    `@State` private var backgroundColor: SwiftUI.Color = .clear
🤖 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/TopNavigationPreview.swift` around
lines 36 - 40, The preview-only `@State` properties in TopNavigationPreview should
be scoped privately to avoid unnecessary exposure and the remaining SwiftLint
warning. Update the local state declarations in the preview view by making the
state members private while keeping their current behavior unchanged; focus on
the TopNavigationPreview view’s variantIndex, leading, trailing, toast, and
backgroundColor state.

Source: Linters/SAST tools

Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift (1)

13-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

@Stateprivate으로 제한해 주세요.

이 상태들은 모두 LoadingPreview 내부 구현 세부사항이라 외부로 열어둘 이유가 없습니다. 지금 상태로는 SwiftLint 경고도 계속 남습니다.

🔧 제안된 수정
-    `@State` var typeOption: TypeOption = .circular
+    `@State` private var typeOption: TypeOption = .circular
-    `@State` var color: SwiftUI.Color = .clear
+    `@State` private var color: SwiftUI.Color = .clear
-    `@State` var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
+    `@State` private var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
-    `@State` var timeout: TimeInterval = 3
+    `@State` private var timeout: TimeInterval = 3
🤖 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/LoadingPreview.swift` around lines
13 - 18, The stored properties in LoadingPreview are implementation details and
should not be publicly exposed; update the `@State` declarations for typeOption,
color, dimmerColor, and timeout to be private so they remain internal to the
view and satisfy SwiftLint. Keep the change localized to LoadingPreview and
preserve the existing default values and behavior.

Source: Linters/SAST tools

🤖 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 `@packages/montage-mcp/data/components.json`:
- Around line 2302-2307: The summary text for the affected component entries is
missing placeholder content, resulting in broken Korean sentences in the
generated MCP metadata. Update the source DocC or the generation path used for
components.json so that the summaries for rawValue and the other affected item
preserve the original placeholders and produce完整 문장, then regenerate the JSON to
ensure the published summary strings are correct.

In `@Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift`:
- Around line 143-145: Inside the Task closure in TextFieldPreview, the property
is being referenced without an explicit instance, which will not compile in this
context. Update the Task block to assign through self by using the
autoCompletionDataSource property on self, and keep the change localized to the
Task in TextFieldPreview so the compiler can resolve the member access
correctly.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 38-40: The TopNavigationPreview state is mixing manually
configured trailing buttons with the search-only trailing state, causing focus
changes to overwrite user-selected options. Split the state in
TopNavigationPreview so the options panel updates only the configured trailing
value, keep search-specific trailing behavior separate, and have
trailingContents derive from an effectiveTrailing value instead of sharing one
mutable array. Use the existing TopNavigationPreview, trailing, and
trailingContents symbols to locate and update the state flow consistently across
the affected sections.

---

Nitpick comments:
In `@Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift`:
- Around line 13-18: The stored properties in LoadingPreview are implementation
details and should not be publicly exposed; update the `@State` declarations for
typeOption, color, dimmerColor, and timeout to be private so they remain
internal to the view and satisfy SwiftLint. Keep the change localized to
LoadingPreview and preserve the existing default values and behavior.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 36-40: The preview-only `@State` properties in TopNavigationPreview
should be scoped privately to avoid unnecessary exposure and the remaining
SwiftLint warning. Update the local state declarations in the preview view by
making the state members private while keeping their current behavior unchanged;
focus on the TopNavigationPreview view’s variantIndex, leading, trailing, toast,
and backgroundColor state.
🪄 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: 862246d3-df2f-4e7e-8ccf-b9f4cc25f2c7

📥 Commits

Reviewing files that changed from the base of the PR and between 80c0a86 and fc31f89.

📒 Files selected for processing (63)
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • packages/montage-mcp/data/components.json
  • packages/montage-mcp/data/tokens.json
  • scripts/build_mcp_data.js
💤 Files with no reviewable changes (2)
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
✅ Files skipped from review due to trivial changes (1)
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
🚧 Files skipped from review as they are similar to previous changes (55)
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • packages/montage-mcp/data/tokens.json
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • scripts/build_mcp_data.js
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

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

36-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

프리뷰 로컬 @Stateprivate으로 닫아 주세요.

이 값들도 모두 뷰 내부 상태라 공개 범위를 넓힐 필요가 없습니다. 현재 변경분만으로도 SwiftLint 경고가 남습니다.

🔧 제안된 수정
-    `@State` var variantIndex: Int = 0
+    `@State` private var variantIndex: Int = 0
-    `@State` var leading = false
+    `@State` private var leading = false
-    `@State` var trailing: [TrailingButton] = []
+    `@State` private var trailing: [TrailingButton] = []
-    `@State` var toast: Toast.Model?
+    `@State` private var toast: Toast.Model?
-    `@State` var backgroundColor: SwiftUI.Color = .clear
+    `@State` private var backgroundColor: SwiftUI.Color = .clear
🤖 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/TopNavigationPreview.swift` around
lines 36 - 40, The preview-only `@State` properties in TopNavigationPreview should
be scoped privately to avoid unnecessary exposure and the remaining SwiftLint
warning. Update the local state declarations in the preview view by making the
state members private while keeping their current behavior unchanged; focus on
the TopNavigationPreview view’s variantIndex, leading, trailing, toast, and
backgroundColor state.

Source: Linters/SAST tools

Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift (1)

13-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

@Stateprivate으로 제한해 주세요.

이 상태들은 모두 LoadingPreview 내부 구현 세부사항이라 외부로 열어둘 이유가 없습니다. 지금 상태로는 SwiftLint 경고도 계속 남습니다.

🔧 제안된 수정
-    `@State` var typeOption: TypeOption = .circular
+    `@State` private var typeOption: TypeOption = .circular
-    `@State` var color: SwiftUI.Color = .clear
+    `@State` private var color: SwiftUI.Color = .clear
-    `@State` var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
+    `@State` private var dimmerColor: SwiftUI.Color = .semantic(.materialDimmer)
-    `@State` var timeout: TimeInterval = 3
+    `@State` private var timeout: TimeInterval = 3
🤖 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/LoadingPreview.swift` around lines
13 - 18, The stored properties in LoadingPreview are implementation details and
should not be publicly exposed; update the `@State` declarations for typeOption,
color, dimmerColor, and timeout to be private so they remain internal to the
view and satisfy SwiftLint. Keep the change localized to LoadingPreview and
preserve the existing default values and behavior.

Source: Linters/SAST tools

🤖 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 `@packages/montage-mcp/data/components.json`:
- Around line 2302-2307: The summary text for the affected component entries is
missing placeholder content, resulting in broken Korean sentences in the
generated MCP metadata. Update the source DocC or the generation path used for
components.json so that the summaries for rawValue and the other affected item
preserve the original placeholders and produce完整 문장, then regenerate the JSON to
ensure the published summary strings are correct.

In `@Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift`:
- Around line 143-145: Inside the Task closure in TextFieldPreview, the property
is being referenced without an explicit instance, which will not compile in this
context. Update the Task block to assign through self by using the
autoCompletionDataSource property on self, and keep the change localized to the
Task in TextFieldPreview so the compiler can resolve the member access
correctly.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 38-40: The TopNavigationPreview state is mixing manually
configured trailing buttons with the search-only trailing state, causing focus
changes to overwrite user-selected options. Split the state in
TopNavigationPreview so the options panel updates only the configured trailing
value, keep search-specific trailing behavior separate, and have
trailingContents derive from an effectiveTrailing value instead of sharing one
mutable array. Use the existing TopNavigationPreview, trailing, and
trailingContents symbols to locate and update the state flow consistently across
the affected sections.

---

Nitpick comments:
In `@Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift`:
- Around line 13-18: The stored properties in LoadingPreview are implementation
details and should not be publicly exposed; update the `@State` declarations for
typeOption, color, dimmerColor, and timeout to be private so they remain
internal to the view and satisfy SwiftLint. Keep the change localized to
LoadingPreview and preserve the existing default values and behavior.

In `@Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift`:
- Around line 36-40: The preview-only `@State` properties in TopNavigationPreview
should be scoped privately to avoid unnecessary exposure and the remaining
SwiftLint warning. Update the local state declarations in the preview view by
making the state members private while keeping their current behavior unchanged;
focus on the TopNavigationPreview view’s variantIndex, leading, trailing, toast,
and backgroundColor state.
🪄 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: 862246d3-df2f-4e7e-8ccf-b9f4cc25f2c7

📥 Commits

Reviewing files that changed from the base of the PR and between 80c0a86 and fc31f89.

📒 Files selected for processing (63)
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/LoadingPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • packages/montage-mcp/data/components.json
  • packages/montage-mcp/data/tokens.json
  • scripts/build_mcp_data.js
💤 Files with no reviewable changes (2)
  • Sources/Blueprint/Sources/Scene/Previews/ProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationPreview.swift
✅ Files skipped from review due to trivial changes (1)
  • Sources/Montage/1 Components/3 Selection And Input/TextArea.swift
🚧 Files skipped from review as they are similar to previous changes (55)
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentListNavigationCoordinator.swift
  • Sources/Blueprint/Sources/Scene/Previews/ProgressIndicatorPreview.swift
  • Sources/Montage/Asset/Localizable.xcstrings
  • Sources/Montage/1 Components/3 Selection And Input/Slider.swift
  • Sources/Blueprint/Sources/Scene/Previews/FlowLayoutPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ShadowPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AccordionPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FilterButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ToastPreview.swift
  • Sources/Blueprint/Sources/Scene/ComponentList/ComponentSection.swift
  • Sources/Blueprint/Sources/Scene/Previews/PaginationDotsPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FallbackViewPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PushBadgePreview.swift
  • packages/montage-mcp/data/tokens.json
  • Sources/Blueprint/Sources/Scene/Previews/SegmentedControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SkeletonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopoverPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarGroupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/FramedStylePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PlayBadgePreview.swift
  • scripts/build_mcp_data.js
  • Sources/Blueprint/Sources/Scene/Previews/PageCounterPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ContentBadgePreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/VerticalProgressTrackerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ColorPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PopupPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ListCellPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SectionHeaderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TabPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ControlPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SliderPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TooltipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/AvatarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/BottomSheetPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CategoryPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ModalNavigationPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/SnackBarPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/PullToRefreshPreview.swift
  • Sources/Montage/1 Components/6 Navigations/TopNavigation.swift
  • Sources/Blueprint/Sources/Scene/Previews/SelectPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ThumbnailPreview.swift
  • Sources/Blueprint/Sources/Utilities/PreviewOption.swift
  • Sources/Blueprint/Blueprint.xcodeproj/project.pbxproj
  • Sources/Blueprint/Sources/Scene/Previews/ChipPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/IconButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/DateTimePickerPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/CardPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/ActionAreaPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/HorizontalProgressTrackerPreview.swift
  • Sources/Montage/1 Components/4 Contents/Thumbnail.swift
  • Sources/Blueprint/Sources/Utilities/PreviewLayout.swift
  • Sources/Blueprint/Sources/Scene/Previews/ButtonPreview.swift
  • Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
🛑 Comments failed to post (3)
packages/montage-mcp/data/components.json (1)

2302-2307: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
GEN="$(fd -HI '^build_mcp_data\.js$' . | head -n1)"
echo "generator: ${GEN:-not found}"

rg -n '인 경우|trailing 전용|rawValue|isLeadingAllowed' \
  packages/montage-mcp/data/components.json \
  "${GEN:-/dev/null}"

Repository: wanteddev/montage-ios

Length of output: 889


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- generator outline ---'
ast-grep outline scripts/build_mcp_data.js --view expanded | sed -n '1,220p'

echo
echo '--- search generator for summary/doc handling ---'
rg -n 'summary|doc|comment|trim|normalize|sanitize|rawValue|isLeadingAllowed|trailing 전용|인 경우' scripts/build_mcp_data.js

echo
echo '--- locate source definitions/usages ---'
rg -n 'rawValue|isLeadingAllowed' packages scripts | sed -n '1,120p'

Repository: wanteddev/montage-ios

Length of output: 2974


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- exact summary strings in repo ---'
rg -n '스낵바가 표시되는 시간\(초\)\. 인 경우 를 반환합니다\.|leading\(왼쪽\)에 배치할 수 있는 리소스인지 여부\. ·은 trailing 전용입니다\.' .

echo
echo '--- nearby generator implementation ---'
sed -n '60,180p' scripts/build_mcp_data.js

Repository: wanteddev/montage-ios

Length of output: 4548


요약 문자열의 자리표시자가 유실됐습니다. packages/montage-mcp/data/components.json:2306packages/montage-mcp/data/components.json:2526의 summary에 인 경우 를 반환합니다. / ·은 trailing 전용입니다. 같은 깨진 문장이 들어가 있습니다. MCP 소비자에게 잘못된 설명이 노출되니, 이 두 항목의 원문 DocC 또는 생성 경로에서 placeholder가 빠지지 않도록 보정해 주세요.

🤖 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 `@packages/montage-mcp/data/components.json` around lines 2302 - 2307, The
summary text for the affected component entries is missing placeholder content,
resulting in broken Korean sentences in the generated MCP metadata. Update the
source DocC or the generation path used for components.json so that the
summaries for rawValue and the other affected item preserve the original
placeholders and produce完整 문장, then regenerate the JSON to ensure the published
summary strings are correct.
Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift (1)

143-145: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C 2 'Task\s*\{' Sources/Blueprint/Sources/Scene/Previews/TextFieldPreview.swift

Repository: wanteddev/montage-ios

Length of output: 404


Task 안에서는 self를 명시해 주세요.
143-145의 Task {} 안에서 autoCompletionDataSource를 그대로 참조하면 컴파일되지 않습니다. self.autoCompletionDataSource = nil로 바꿔 주세요.

🤖 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/TextFieldPreview.swift` around lines
143 - 145, Inside the Task closure in TextFieldPreview, the property is being
referenced without an explicit instance, which will not compile in this context.
Update the Task block to assign through self by using the
autoCompletionDataSource property on self, and keep the change localized to the
Task in TextFieldPreview so the compiler can resolve the member access
correctly.

Source: Path instructions

Sources/Blueprint/Sources/Scene/Previews/TopNavigationPreview.swift (1)

38-40: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

수동 trailing 옵션과 search 전용 trailing 상태를 같은 배열로 관리하면 상태가 깨집니다.

지금은 옵션 패널에서 추가한 trailing 값과 .search variant의 포커스 연동 값이 같은 상태를 공유합니다. 그래서 사용자가 옵션에서 추가한 버튼이 포커스 변화로 덮어써지고, search variant를 다녀온 뒤 비-search variant의 trailing 구성이 이전 포커스 이력에 따라 달라집니다. 수동 설정 상태와 search 전용 표시 상태를 분리해서, 최종 trailingContents만 계산해서 만드는 편이 안전합니다.

🔧 방향 제안
-    `@State` private var trailing: [TrailingButton] = []
+    `@State` private var configuredTrailing: [TrailingButton] = []
+
+    private var effectiveTrailing: [TrailingButton] {
+        isSearchVariant && focused ? [.text] : configuredTrailing
+    }

옵션 패널은 configuredTrailing만 수정하고, trailingContentseffectiveTrailing을 기준으로 만들면 포커스 변화가 사용자 설정을 덮어쓰지 않게 됩니다.

Also applies to: 123-133, 178-183

🧰 Tools
🪛 SwiftLint (0.64.0)

[Warning] 38-38: SwiftUI state properties should be private

(private_swiftui_state)


[Warning] 39-39: SwiftUI state properties should be private

(private_swiftui_state)


[Warning] 40-40: SwiftUI state properties should be private

(private_swiftui_state)

🤖 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/TopNavigationPreview.swift` around
lines 38 - 40, The TopNavigationPreview state is mixing manually configured
trailing buttons with the search-only trailing state, causing focus changes to
overwrite user-selected options. Split the state in TopNavigationPreview so the
options panel updates only the configured trailing value, keep search-specific
trailing behavior separate, and have trailingContents derive from an
effectiveTrailing value instead of sharing one mutable array. Use the existing
TopNavigationPreview, trailing, and trailingContents symbols to locate and
update the state flow consistently across the affected sections.

- MCP 데이터 생성기: abstractText가 codeVoice·reference·중첩 inline까지 포함하도록 보완.
  기존엔 text 세그먼트만 이어붙여 'スナックバ... .infinity인 경우 ...' 처럼 placeholder가
  빠진 깨진 한국어 요약이 생성되던 문제를 수정하고 components.json/tokens.json 재생성
- TextFieldPreview: Task 클로저 내 autoCompletionDataSource를 self로 명시
- LoadingPreview·TopNavigationPreview: 프리뷰 로컬 @State를 private으로 제한 (SwiftLint)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8gTT3K3Hci759WS9qMf8r
@knine79

knine79 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

리뷰(pullrequestreview-4589975454) 반영 완료 (124eff8). 인라인 코멘트가 GitHub 오류로 등록 실패해 본문에만 남아, 항목별로 여기에 정리합니다.

Actionable (3)

  1. packages/montage-mcp/data/components.json — 깨진 한국어 요약
    근본 원인은 생성기(build_mcp_data.js)의 abstractTexttext 세그먼트만 이어붙이고 codeVoice(`.infinity`reference를 버린 것이었습니다. codeVoice·reference 제목·중첩 inline까지 포함하도록 보완하고 재생성했습니다.

    • 예: "스낵바가 표시되는 시간(초). 인 경우 를 반환합니다.""스낵바가 표시되는 시간(초). .infinity인 경우 Double.infinity를 반환합니다."
    • 그 외 다수 요약(기본값: .labelNormal, variant가 .search일 때만 등)도 placeholder가 복원됐습니다.
  2. TextFieldPreview.swift — Task 내 self 누락
    Task { autoCompletionDataSource = nil }Task { self.autoCompletionDataSource = nil }로 명시했습니다.

  3. LoadingPreview.swift @State private화 ✅ (아래 nitpick과 함께 처리)

Nitpick (2)

  1. LoadingPreview.swift 프리뷰 로컬 @State private ✅ — isLoading/typeOption/color/dimmerColor/timeout 모두 private으로 제한.
  2. TopNavigationPreview.swift 프리뷰 로컬 @State private ✅ — variantIndex/leading/trailing/toast/backgroundColor 및 나머지 비공개 누락 @State까지 private으로 제한해 같은 SwiftLint 경고가 남지 않게 했습니다.

검증: Montage(docc)·Blueprint 빌드 통과, make 재생성 후 components.json/tokens.json에 깨진 요약·Inherited from 누출 없음 확인.

@github-actions github-actions Bot added accepted This issue has been reviewed. and removed in review This issue requires a review. labels Jun 30, 2026
Base automatically changed from feature/WRP-1247 to release/4.0.0 July 6, 2026 04:47
…y-faraday-ac366a

# Conflicts:
#	Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
@github-actions github-actions Bot added in review This issue requires a review. and removed accepted This issue has been reviewed. labels Jul 6, 2026
@knine79 knine79 marked this pull request as ready for review July 6, 2026 05:57
@knine79 knine79 requested a review from a team as a code owner July 6, 2026 05:57
@knine79 knine79 requested review from szzang-kr and removed request for a team July 6, 2026 05:57
@knine79 knine79 merged commit 32046fc into release/4.0.0 Jul 6, 2026
2 of 3 checks passed
@knine79 knine79 deleted the refactor/blueprint-preview-layout branch July 6, 2026 05:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in review This issue requires a review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant