swift-code-reviewer-skill 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +44 -162
  2. package/README.md +91 -21
  3. package/SKILL.md +107 -725
  4. package/bin/install.js +87 -22
  5. package/package.json +16 -2
  6. package/references/companion-skills.md +70 -0
  7. package/skills/README.md +43 -0
  8. package/skills/swift-concurrency/NOTICE.md +18 -0
  9. package/skills/swift-concurrency/SKILL.md +235 -0
  10. package/skills/swift-concurrency/references/actors.md +640 -0
  11. package/skills/swift-concurrency/references/async-await-basics.md +249 -0
  12. package/skills/swift-concurrency/references/async-sequences.md +635 -0
  13. package/skills/swift-concurrency/references/core-data.md +533 -0
  14. package/skills/swift-concurrency/references/glossary.md +96 -0
  15. package/skills/swift-concurrency/references/linting.md +38 -0
  16. package/skills/swift-concurrency/references/memory-management.md +542 -0
  17. package/skills/swift-concurrency/references/migration.md +721 -0
  18. package/skills/swift-concurrency/references/performance.md +574 -0
  19. package/skills/swift-concurrency/references/sendable.md +578 -0
  20. package/skills/swift-concurrency/references/tasks.md +604 -0
  21. package/skills/swift-concurrency/references/testing.md +565 -0
  22. package/skills/swift-concurrency/references/threading.md +452 -0
  23. package/skills/swift-expert/NOTICE.md +18 -0
  24. package/skills/swift-expert/SKILL.md +226 -0
  25. package/skills/swift-expert/references/async-concurrency.md +363 -0
  26. package/skills/swift-expert/references/memory-performance.md +380 -0
  27. package/skills/swift-expert/references/protocol-oriented.md +357 -0
  28. package/skills/swift-expert/references/swiftui-patterns.md +294 -0
  29. package/skills/swift-expert/references/testing-patterns.md +402 -0
  30. package/skills/swift-testing/NOTICE.md +18 -0
  31. package/skills/swift-testing/SKILL.md +295 -0
  32. package/skills/swift-testing/references/async-testing.md +245 -0
  33. package/skills/swift-testing/references/dump-snapshot-testing.md +265 -0
  34. package/skills/swift-testing/references/fixtures.md +193 -0
  35. package/skills/swift-testing/references/integration-testing.md +189 -0
  36. package/skills/swift-testing/references/migration-xctest.md +301 -0
  37. package/skills/swift-testing/references/parameterized-tests.md +171 -0
  38. package/skills/swift-testing/references/snapshot-testing.md +201 -0
  39. package/skills/swift-testing/references/test-doubles.md +243 -0
  40. package/skills/swift-testing/references/test-organization.md +231 -0
  41. package/skills/swiftui-expert-skill/NOTICE.md +18 -0
  42. package/skills/swiftui-expert-skill/SKILL.md +281 -0
  43. package/skills/swiftui-expert-skill/references/accessibility-patterns.md +151 -0
  44. package/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  45. package/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  46. package/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  47. package/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  48. package/skills/swiftui-expert-skill/references/charts.md +602 -0
  49. package/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  50. package/skills/swiftui-expert-skill/references/latest-apis.md +464 -0
  51. package/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  52. package/skills/swiftui-expert-skill/references/liquid-glass.md +414 -0
  53. package/skills/swiftui-expert-skill/references/list-patterns.md +394 -0
  54. package/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  55. package/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  56. package/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  57. package/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  58. package/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  59. package/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  60. package/skills/swiftui-expert-skill/references/state-management.md +417 -0
  61. package/skills/swiftui-expert-skill/references/view-structure.md +389 -0
  62. package/skills/swiftui-ui-patterns/NOTICE.md +18 -0
  63. package/skills/swiftui-ui-patterns/SKILL.md +95 -0
  64. package/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  65. package/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  66. package/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  67. package/skills/swiftui-ui-patterns/references/controls.md +57 -0
  68. package/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  69. package/skills/swiftui-ui-patterns/references/focus.md +90 -0
  70. package/skills/swiftui-ui-patterns/references/form.md +97 -0
  71. package/skills/swiftui-ui-patterns/references/grids.md +71 -0
  72. package/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  73. package/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  74. package/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  75. package/skills/swiftui-ui-patterns/references/list.md +86 -0
  76. package/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  77. package/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  78. package/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  79. package/skills/swiftui-ui-patterns/references/media.md +73 -0
  80. package/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  81. package/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  82. package/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  83. package/skills/swiftui-ui-patterns/references/performance.md +62 -0
  84. package/skills/swiftui-ui-patterns/references/previews.md +48 -0
  85. package/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  86. package/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  87. package/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  88. package/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  89. package/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  90. package/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  91. package/skills/swiftui-ui-patterns/references/theming.md +71 -0
  92. package/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  93. package/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
  94. package/templates/agents/swift-code-reviewer.md +78 -0
  95. package/templates/commands/review.md +56 -0
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: swiftui-expert-skill
3
+ description: Write, review, or improve SwiftUI code following best practices for state management, view composition, performance, macOS-specific APIs, and iOS 26+ Liquid Glass adoption. Use when building new SwiftUI features, refactoring existing views, reviewing code quality, or adopting modern SwiftUI patterns.
4
+ ---
5
+
6
+ # SwiftUI Expert Skill
7
+
8
+ ## Overview
9
+ Use this skill to build, review, or improve SwiftUI features with correct state management, optimal view composition, and iOS 26+ Liquid Glass styling. Prioritize native APIs, Apple design guidance, and performance-conscious patterns. This skill focuses on facts and best practices without enforcing specific architectural patterns.
10
+
11
+ ## Workflow Decision Tree
12
+
13
+ ### 1) Review existing SwiftUI code
14
+ - **First, consult `references/latest-apis.md`** to ensure only current, non-deprecated APIs are used
15
+ - Check property wrapper usage against the selection guide (see `references/state-management.md`)
16
+ - Verify view composition follows extraction rules (see `references/view-structure.md`)
17
+ - Check performance patterns are applied (see `references/performance-patterns.md`)
18
+ - Verify list patterns use stable identity (see `references/list-patterns.md`)
19
+ - Check animation patterns for correctness (see `references/animation-basics.md`, `references/animation-transitions.md`)
20
+ - Review accessibility: proper grouping, traits, Dynamic Type support (see `references/accessibility-patterns.md`)
21
+ - Check chart patterns for correct mark usage, stable data identity, and availability gating (see `references/charts.md`; for accessibility and fallback strategies see `references/charts-accessibility.md`)
22
+ - For macOS targets: verify correct use of macOS-specific APIs and patterns (see `references/macos-scenes.md`, `references/macos-window-styling.md`, `references/macos-views.md`)
23
+ - Inspect Liquid Glass usage for correctness and consistency (see `references/liquid-glass.md`)
24
+ - Validate iOS 26+ availability handling with sensible fallbacks
25
+
26
+ ### 2) Improve existing SwiftUI code
27
+ - **First, consult `references/latest-apis.md`** to replace any deprecated APIs with their modern equivalents
28
+ - Audit state management for correct wrapper selection (see `references/state-management.md`)
29
+ - Extract complex views into separate subviews (see `references/view-structure.md`)
30
+ - Refactor hot paths to minimize redundant state updates (see `references/performance-patterns.md`)
31
+ - Ensure ForEach uses stable identity (see `references/list-patterns.md`)
32
+ - Improve animation patterns (use value parameter, proper transitions, see `references/animation-basics.md`, `references/animation-transitions.md`)
33
+ - Improve accessibility: use `Button` over tap gestures, add `@ScaledMetric` for Dynamic Type (see `references/accessibility-patterns.md`)
34
+ - Review chart code for correct modifier scope, styling, and accessibility (see `references/charts.md`, `references/charts-accessibility.md`)
35
+ - For macOS targets: adopt macOS-specific APIs (MenuBarExtra, Settings, Table, Commands, etc.) where appropriate (see `references/macos-scenes.md`, `references/macos-window-styling.md`, `references/macos-views.md`)
36
+ - Suggest image downsampling when `UIImage(data:)` is used (as optional optimization, see `references/image-optimization.md`)
37
+ - Adopt Liquid Glass only when explicitly requested by the user
38
+
39
+ ### 3) Implement new SwiftUI feature
40
+ - **First, consult `references/latest-apis.md`** to use only current, non-deprecated APIs for the target deployment version
41
+ - Design data flow first: identify owned vs injected state (see `references/state-management.md`)
42
+ - Structure views for optimal diffing (extract subviews early, see `references/view-structure.md`)
43
+ - Keep business logic in services and models for testability (see `references/layout-best-practices.md`)
44
+ - Use correct animation patterns (implicit vs explicit, transitions, see `references/animation-basics.md`, `references/animation-transitions.md`, `references/animation-advanced.md`)
45
+ - Use `Button` for tappable elements, add accessibility grouping and labels (see `references/accessibility-patterns.md`)
46
+ - For charts: use correct mark types, stable data identity, and gate iOS 17+/18+/26+ APIs (see `references/charts.md`; for accessibility see `references/charts-accessibility.md`)
47
+ - For macOS targets: use macOS-specific scenes (see `references/macos-scenes.md`), window styling (see `references/macos-window-styling.md`), and views like HSplitView, Table (see `references/macos-views.md`)
48
+ - Apply glass effects after layout/appearance modifiers (see `references/liquid-glass.md`)
49
+ - Gate iOS 26+ features with `#available` and provide fallbacks
50
+
51
+ ## Core Guidelines
52
+
53
+ ### State Management
54
+ - `@State` must be `private`; use for internal view state
55
+ - `@Binding` only when a child needs to **modify** parent state
56
+ - `@StateObject` when view **creates** the object; `@ObservedObject` when **injected**
57
+ - iOS 17+: Use `@State` with `@Observable` classes; use `@Bindable` for injected observables needing bindings
58
+ - Use `let` for read-only values; `var` + `.onChange()` for reactive reads
59
+ - Never pass values into `@State` or `@StateObject` — they only accept initial values
60
+ - Nested `ObservableObject` doesn't propagate changes — pass nested objects directly; `@Observable` handles nesting fine
61
+
62
+ ### View Composition
63
+ - Extract complex views into separate subviews for better readability and performance
64
+ - Prefer modifiers over conditional views for state changes (maintains view identity)
65
+ - Keep view `body` simple and pure (no side effects or complex logic)
66
+ - Use `@ViewBuilder` functions only for small, simple sections
67
+ - Prefer `@ViewBuilder let content: Content` over closure-based content properties
68
+ - Keep business logic in services and models; views should orchestrate UI flow
69
+ - Action handlers should reference methods, not contain inline logic
70
+ - Views should work in any context (don't assume screen size or presentation style)
71
+
72
+ ### Performance
73
+ - Pass only needed values to views (avoid large "config" or "context" objects)
74
+ - Eliminate unnecessary dependencies to reduce update fan-out
75
+ - Consider per-item `@Observable` state objects in lists to narrow update/dependency scope
76
+ - Consider whether frequently-changing values belong in the environment; prefer more local state when it reduces unnecessary view updates
77
+ - Check for value changes before assigning state in hot paths
78
+ - Avoid redundant state updates in `onReceive`, `onChange`, scroll handlers
79
+ - Minimize work in frequently executed code paths
80
+ - Use `LazyVStack`/`LazyHStack` for large lists
81
+ - Use stable identity for `ForEach` (never `.indices` for dynamic content)
82
+ - Ensure constant number of views per `ForEach` element
83
+ - Avoid inline filtering in `ForEach` (prefilter and cache)
84
+ - Avoid `AnyView` in list rows
85
+ - Consider POD views for fast diffing (or wrap expensive views in POD parents)
86
+ - Suggest image downsampling when `UIImage(data:)` is encountered (as optional optimization)
87
+ - Avoid layout thrash (deep hierarchies, excessive `GeometryReader`)
88
+ - Gate frequent geometry updates by thresholds
89
+ - Use `Self._logChanges()` or `Self._printChanges()` to debug unexpected view updates
90
+ - `Shape.path()`, `visualEffect`, `Layout`, and `onGeometryChange` closures may run off the main thread — capture values instead of accessing `@MainActor` state
91
+
92
+ ### Animations
93
+ - Use `.animation(_:value:)` with value parameter (deprecated version without value is too broad)
94
+ - Use `withAnimation` for event-driven animations (button taps, gestures)
95
+ - Prefer transforms (`offset`, `scale`, `rotation`) over layout changes (`frame`) for performance
96
+ - Transitions require animations outside the conditional structure
97
+ - Custom `Animatable` implementations must have explicit `animatableData` (or use `@Animatable` macro on iOS 26+)
98
+ - iOS 26+: Use `@Animatable` macro to auto-synthesize `animatableData`; use `@AnimatableIgnored` to exclude properties
99
+ - Use `.phaseAnimator` for multi-step sequences (iOS 17+)
100
+ - Use `.keyframeAnimator` for precise timing control (iOS 17+)
101
+ - Animation completion handlers need `.transaction(value:)` for reexecution
102
+ - Implicit animations override explicit animations (later in view tree wins)
103
+
104
+ ### Accessibility
105
+ - Prefer `Button` over `onTapGesture` for tappable elements (free VoiceOver support)
106
+ - Use `@ScaledMetric` for custom numeric values that should scale with Dynamic Type
107
+ - Group related elements with `accessibilityElement(children: .combine)` for joined labels
108
+ - Provide `accessibilityLabel` when default labels are unclear or missing
109
+ - Use `accessibilityRepresentation` for custom controls that should behave like native ones
110
+
111
+ ### Liquid Glass (iOS 26+)
112
+ **Only adopt when explicitly requested by the user.**
113
+ - Use native `glassEffect`, `GlassEffectContainer`, and glass button styles
114
+ - Wrap multiple glass elements in `GlassEffectContainer`
115
+ - Apply `.glassEffect()` after layout and visual modifiers
116
+ - Use `.interactive()` only for tappable/focusable elements
117
+ - Use `glassEffectID` with `@Namespace` for morphing transitions
118
+
119
+ ## Quick Reference
120
+
121
+ ### Property Wrapper Selection
122
+ | Wrapper | Use When |
123
+ |---------|----------|
124
+ | `@State` | Internal view state (must be `private`) |
125
+ | `@Binding` | Child modifies parent's state |
126
+ | `@StateObject` | View owns an `ObservableObject` |
127
+ | `@ObservedObject` | View receives an `ObservableObject` |
128
+ | `@Bindable` | iOS 17+: Injected `@Observable` needing bindings |
129
+ | `let` | Read-only value from parent |
130
+ | `var` | Read-only value watched via `.onChange()` |
131
+
132
+ ### Liquid Glass Patterns
133
+ ```swift
134
+ // Basic glass effect with fallback
135
+ if #available(iOS 26, *) {
136
+ content
137
+ .padding()
138
+ .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
139
+ } else {
140
+ content
141
+ .padding()
142
+ .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
143
+ }
144
+
145
+ // Grouped glass elements
146
+ GlassEffectContainer(spacing: 24) {
147
+ HStack(spacing: 24) {
148
+ GlassButton1()
149
+ GlassButton2()
150
+ }
151
+ }
152
+
153
+ // Glass buttons
154
+ Button("Confirm") { }
155
+ .buttonStyle(.glassProminent)
156
+ ```
157
+
158
+ ## Review Checklist
159
+
160
+ ### Latest APIs (see `references/latest-apis.md`)
161
+ - [ ] No deprecated modifiers used (check against the quick lookup table)
162
+ - [ ] API choices match the project's minimum deployment target
163
+
164
+ ### State Management
165
+ - [ ] `@State` properties are `private`
166
+ - [ ] `@Binding` only where child modifies parent state
167
+ - [ ] `@StateObject` for owned, `@ObservedObject` for injected
168
+ - [ ] iOS 17+: `@State` with `@Observable`, `@Bindable` for injected
169
+ - [ ] Passed values NOT declared as `@State` or `@StateObject`
170
+ - [ ] Nested `ObservableObject` avoided (or passed directly to child views)
171
+
172
+ ### Sheets & Navigation (see `references/sheet-navigation-patterns.md`)
173
+ - [ ] Using `.sheet(item:)` for model-based sheets
174
+ - [ ] Sheets own their actions and dismiss internally
175
+
176
+ ### ScrollView (see `references/scroll-patterns.md`)
177
+ - [ ] Using `ScrollViewReader` with stable IDs for programmatic scrolling
178
+
179
+ ### View Structure (see `references/view-structure.md`)
180
+ - [ ] Using modifiers instead of conditionals for state changes
181
+ - [ ] Complex views extracted to separate subviews
182
+ - [ ] Container views use `@ViewBuilder let content: Content`
183
+ - [ ] `.compositingGroup()` before `.clipShape()` on layered views
184
+
185
+ ### Performance (see `references/performance-patterns.md`)
186
+ - [ ] View `body` kept simple and pure (no side effects)
187
+ - [ ] Passing only needed values (not large config objects)
188
+ - [ ] Eliminating unnecessary dependencies
189
+ - [ ] Consider making @Observable dependencies as granular as needed (for example, per-item data for list rows) when it helps performance
190
+ - [ ] State updates check for value changes before assigning
191
+ - [ ] Hot paths minimize state updates
192
+ - [ ] No object creation in `body`
193
+ - [ ] Heavy computation moved out of `body`
194
+ - [ ] Sendable closures capture values instead of accessing @MainActor state
195
+
196
+ ### List Patterns (see `references/list-patterns.md`)
197
+ - [ ] ForEach uses stable identity (not `.indices`)
198
+ - [ ] Constant number of views per ForEach element
199
+ - [ ] No inline filtering in ForEach
200
+ - [ ] No `AnyView` in list rows
201
+
202
+ ### Layout (see `references/layout-best-practices.md`)
203
+ - [ ] Avoiding layout thrash (deep hierarchies, excessive GeometryReader)
204
+ - [ ] Gating frequent geometry updates by thresholds
205
+ - [ ] Business logic kept in services and models (not in views)
206
+ - [ ] Action handlers reference methods (not inline logic)
207
+ - [ ] Using relative layout (not hard-coded constants)
208
+ - [ ] Views work in any context (context-agnostic)
209
+
210
+ ### Animations (see `references/animation-basics.md`, `references/animation-transitions.md`, `references/animation-advanced.md`)
211
+ - [ ] Using `.animation(_:value:)` with value parameter
212
+ - [ ] Using `withAnimation` for event-driven animations
213
+ - [ ] Transitions paired with animations outside conditional structure
214
+ - [ ] Custom `Animatable` has explicit `animatableData` (or `@Animatable` macro on iOS 26+)
215
+ - [ ] Preferring transforms over layout changes for animation performance
216
+ - [ ] Phase animations for multi-step sequences (iOS 17+)
217
+ - [ ] Keyframe animations for precise timing (iOS 17+)
218
+ - [ ] Completion handlers use `.transaction(value:)` for reexecution
219
+
220
+ ### Accessibility (see `references/accessibility-patterns.md`)
221
+ - [ ] `Button` used instead of `onTapGesture` for tappable elements
222
+ - [ ] `@ScaledMetric` used for custom values that should scale with Dynamic Type
223
+ - [ ] Related elements grouped with `accessibilityElement(children:)`
224
+ - [ ] Custom controls use `accessibilityRepresentation` when appropriate
225
+
226
+ ### Charts (see `references/charts.md`, `references/charts-accessibility.md`)
227
+ - [ ] `import Charts` is present in files using chart types
228
+ - [ ] Chart data models use `Identifiable` (or explicit `id:` key path)
229
+ - [ ] Chart-wide modifiers applied to `Chart`, not individual marks
230
+ - [ ] iOS 17+ APIs (`SectorMark`, selection, scrollable axes) are availability-gated
231
+ - [ ] iOS 18+ APIs (plot types like `LinePlot`, `AreaPlot`) are availability-gated
232
+ - [ ] iOS 26+ APIs (`Chart3D`, `SurfacePlot`) are availability-gated
233
+ - [ ] Meaningful `.value()` labels used for axes and accessibility
234
+ - [ ] `foregroundStyle(by:)` used for categorical series (not manual per-mark colors)
235
+
236
+ ### macOS APIs (see `references/macos-scenes.md`, `references/macos-window-styling.md`, `references/macos-views.md`)
237
+ - [ ] Using `Settings` scene for preferences (not a custom window)
238
+ - [ ] Using `MenuBarExtra` for menu bar items (not AppKit `NSStatusItem`)
239
+ - [ ] Using `Commands` / `CommandGroup` / `CommandMenu` for menu bar menus
240
+ - [ ] `Table` adapts for compact size classes on iOS (first column shows combined info)
241
+ - [ ] Window sizing configured with `defaultSize`, `windowResizability`, and `frame(minWidth:minHeight:)`
242
+ - [ ] macOS-only code wrapped in `#if os(macOS)` conditionals
243
+ - [ ] Using `NSViewRepresentable` with proper `makeNSView`/`updateNSView` lifecycle
244
+ - [ ] Using `NavigationSplitView` (not `HSplitView`) for sidebar-based navigation
245
+ - [ ] `HSplitView`/`VSplitView` reserved for IDE-style equal peer panes
246
+
247
+ ### Liquid Glass (iOS 26+)
248
+ - [ ] `#available(iOS 26, *)` with fallback for Liquid Glass
249
+ - [ ] Multiple glass views wrapped in `GlassEffectContainer`
250
+ - [ ] `.glassEffect()` applied after layout/appearance modifiers
251
+ - [ ] `.interactive()` only on user-interactable elements
252
+ - [ ] Shapes and tints consistent across related elements
253
+
254
+ ## References
255
+ - `references/latest-apis.md` - **Required reading for all workflows.** Version-segmented guide of deprecated-to-modern API transitions (iOS 15+ through iOS 26+)
256
+ - `references/state-management.md` - Property wrappers and data flow
257
+ - `references/view-structure.md` - View composition, extraction, and container patterns
258
+ - `references/performance-patterns.md` - Performance optimization techniques and anti-patterns
259
+ - `references/list-patterns.md` - ForEach identity, stability, Table (iOS 16+), and list best practices
260
+ - `references/layout-best-practices.md` - Layout patterns, context-agnostic views, and testability
261
+ - `references/accessibility-patterns.md` - Accessibility traits, grouping, Dynamic Type, and VoiceOver
262
+ - `references/animation-basics.md` - Core animation concepts, implicit/explicit animations, timing, performance
263
+ - `references/animation-transitions.md` - Transitions, custom transitions, Animatable protocol
264
+ - `references/animation-advanced.md` - Transactions, phase/keyframe animations (iOS 17+), completion handlers (iOS 17+), `@Animatable` macro (iOS 26+)
265
+ - `references/charts.md` - Swift Charts marks, axes, selection, styling, composition, and Chart3D (iOS 26+)
266
+ - `references/charts-accessibility.md` - Charts accessibility (VoiceOver, Audio Graph, AXChartDescriptorRepresentable), fallback strategies, and WWDC sessions
267
+ - `references/sheet-navigation-patterns.md` - Sheet presentation, NavigationSplitView, Inspector, and navigation patterns
268
+ - `references/scroll-patterns.md` - ScrollView patterns and programmatic scrolling
269
+ - `references/image-optimization.md` - AsyncImage, image downsampling, and optimization
270
+ - `references/liquid-glass.md` - iOS 26+ Liquid Glass API
271
+ - `references/macos-scenes.md` - macOS scene types: Settings, MenuBarExtra, WindowGroup, Window, UtilityWindow, DocumentGroup
272
+ - `references/macos-window-styling.md` - macOS window configuration: toolbar styles, sizing, positioning, NavigationSplitView, Inspector, Commands
273
+ - `references/macos-views.md` - macOS views and components: HSplitView, VSplitView, Table, PasteButton, file dialogs, drag & drop, AppKit interop
274
+
275
+ ## Philosophy
276
+
277
+ This skill focuses on **facts and best practices**, not architectural opinions:
278
+ - We don't enforce specific architectures (e.g., MVVM, VIPER)
279
+ - We do encourage separating business logic for testability
280
+ - We optimize for performance and maintainability
281
+ - We follow Apple's Human Interface Guidelines and API design patterns
@@ -0,0 +1,151 @@
1
+ # SwiftUI Accessibility Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [Core Principle](#core-principle)
6
+ - [Dynamic Type with @ScaledMetric](#dynamic-type-with-scaledmetric)
7
+ - [Accessibility Traits](#accessibility-traits)
8
+ - [Element Grouping](#element-grouping)
9
+ - [Custom Controls](#custom-controls)
10
+ - [Summary Checklist](#summary-checklist)
11
+
12
+ ## Core Principle
13
+
14
+ Prefer `Button` over `onTapGesture` for tappable elements. `Button` provides VoiceOver support, focus handling, and proper traits for free.
15
+
16
+ ## Dynamic Type with @ScaledMetric
17
+
18
+ System `Text` scales with Dynamic Type automatically. For custom numeric values (padding, image sizes, spacing), use `@ScaledMetric`:
19
+
20
+ ```swift
21
+ struct ProfileHeader: View {
22
+ @ScaledMetric private var avatarSize = 60.0
23
+ @ScaledMetric private var spacing = 12.0
24
+
25
+ var body: some View {
26
+ HStack(spacing: spacing) {
27
+ Image("avatar")
28
+ .resizable()
29
+ .frame(width: avatarSize, height: avatarSize)
30
+ Text("Username")
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Specify a `relativeTo` text style when the value should scale relative to a specific font size:
37
+
38
+ ```swift
39
+ @ScaledMetric(relativeTo: .caption) private var iconSize = 16.0
40
+ ```
41
+
42
+ ## Accessibility Traits
43
+
44
+ Use `accessibilityAddTraits` and `accessibilityRemoveTraits` for state-driven traits:
45
+
46
+ ```swift
47
+ Text(item.title)
48
+ .accessibilityAddTraits(item.isSelected ? [.isSelected, .isButton] : .isButton)
49
+ ```
50
+
51
+ Use `.disabled(true)` to make VoiceOver announce "Dimmed" for non-interactive elements.
52
+
53
+ ## Element Grouping
54
+
55
+ ### .combine -- Auto-join child labels
56
+
57
+ ```swift
58
+ HStack {
59
+ Image(systemName: "star.fill")
60
+ Text("Favorites")
61
+ Text("(\(count))")
62
+ }
63
+ .accessibilityElement(children: .combine)
64
+ ```
65
+
66
+ VoiceOver reads all child labels as one element, separated by commas.
67
+
68
+ ### .ignore -- Manual label for container
69
+
70
+ ```swift
71
+ HStack {
72
+ Text(item.name)
73
+ Spacer()
74
+ Text(item.price)
75
+ }
76
+ .accessibilityElement(children: .ignore)
77
+ .accessibilityLabel("\(item.name), \(item.price)")
78
+ ```
79
+
80
+ ### .contain -- Semantic grouping
81
+
82
+ ```swift
83
+ HStack {
84
+ ForEach(tabs) { tab in
85
+ TabButton(tab: tab)
86
+ }
87
+ }
88
+ .accessibilityElement(children: .contain)
89
+ .accessibilityLabel("Tab bar")
90
+ ```
91
+
92
+ VoiceOver announces the container name when focus enters/exits.
93
+
94
+ ## Custom Controls
95
+
96
+ ### Adjustable controls (increment/decrement)
97
+
98
+ ```swift
99
+ PageControl(selectedIndex: $selectedIndex, pageCount: pageCount)
100
+ .accessibilityElement()
101
+ .accessibilityValue("Page \(selectedIndex + 1) of \(pageCount)")
102
+ .accessibilityAdjustableAction { direction in
103
+ switch direction {
104
+ case .increment:
105
+ guard selectedIndex < pageCount - 1 else { break }
106
+ selectedIndex += 1
107
+ case .decrement:
108
+ guard selectedIndex > 0 else { break }
109
+ selectedIndex -= 1
110
+ @unknown default:
111
+ break
112
+ }
113
+ }
114
+ ```
115
+
116
+ ### Representing custom views as native controls
117
+
118
+ When a custom view should behave like a native control for accessibility:
119
+
120
+ ```swift
121
+ HStack {
122
+ Text(label)
123
+ Toggle("", isOn: $isOn)
124
+ }
125
+ .accessibilityRepresentation {
126
+ Toggle(label, isOn: $isOn)
127
+ }
128
+ ```
129
+
130
+ ### Label-content pairing
131
+
132
+ ```swift
133
+ @Namespace private var ns
134
+
135
+ HStack {
136
+ Text("Volume")
137
+ .accessibilityLabeledPair(role: .label, id: "volume", in: ns)
138
+ Slider(value: $volume)
139
+ .accessibilityLabeledPair(role: .content, id: "volume", in: ns)
140
+ }
141
+ ```
142
+
143
+ ## Summary Checklist
144
+
145
+ - [ ] Use `Button` instead of `onTapGesture` for tappable elements
146
+ - [ ] Use `@ScaledMetric` for custom values that should scale with Dynamic Type
147
+ - [ ] Group related elements with `accessibilityElement(children:)`
148
+ - [ ] Provide `accessibilityLabel` when default labels are unclear
149
+ - [ ] Use `accessibilityRepresentation` for custom controls
150
+ - [ ] Use `accessibilityAdjustableAction` for increment/decrement controls
151
+ - [ ] Ensure navigation flow is logical when using VoiceOver grouping