claudecode-omc 5.6.7 → 5.6.8

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 (123) hide show
  1. package/.local/skills/THIRD_PARTY_LICENSES/AvdLee-SwiftUI-Agent-Skill.LICENSE +21 -0
  2. package/.local/skills/THIRD_PARTY_LICENSES/Dimillian-Skills.LICENSE +21 -0
  3. package/.local/skills/THIRD_PARTY_LICENSES/README.md +36 -0
  4. package/.local/skills/THIRD_PARTY_LICENSES/twostraws-swiftui-agent-skill.LICENSE +21 -0
  5. package/.local/skills/ios-debugger-agent/SKILL.md +51 -0
  6. package/.local/skills/ios-debugger-agent/agents/openai.yaml +4 -0
  7. package/.local/skills/swift-concurrency-expert/SKILL.md +105 -0
  8. package/.local/skills/swift-concurrency-expert/agents/openai.yaml +4 -0
  9. package/.local/skills/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
  10. package/.local/skills/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
  11. package/.local/skills/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
  12. package/.local/skills/swiftui-expert-skill/SKILL.md +162 -0
  13. package/.local/skills/swiftui-expert-skill/references/accessibility-patterns.md +215 -0
  14. package/.local/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  15. package/.local/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  16. package/.local/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  17. package/.local/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  18. package/.local/skills/swiftui-expert-skill/references/charts.md +602 -0
  19. package/.local/skills/swiftui-expert-skill/references/focus-patterns.md +299 -0
  20. package/.local/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  21. package/.local/skills/swiftui-expert-skill/references/latest-apis.md +488 -0
  22. package/.local/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  23. package/.local/skills/swiftui-expert-skill/references/liquid-glass.md +423 -0
  24. package/.local/skills/swiftui-expert-skill/references/list-patterns.md +446 -0
  25. package/.local/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  26. package/.local/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  27. package/.local/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  28. package/.local/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  29. package/.local/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  30. package/.local/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  31. package/.local/skills/swiftui-expert-skill/references/state-management.md +388 -0
  32. package/.local/skills/swiftui-expert-skill/references/text-patterns.md +32 -0
  33. package/.local/skills/swiftui-expert-skill/references/trace-analysis.md +295 -0
  34. package/.local/skills/swiftui-expert-skill/references/trace-recording.md +134 -0
  35. package/.local/skills/swiftui-expert-skill/references/view-structure.md +780 -0
  36. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/analyze_trace.cpython-313.pyc +0 -0
  37. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/record_trace.cpython-313.pyc +0 -0
  38. package/.local/skills/swiftui-expert-skill/scripts/analyze_trace.py +301 -0
  39. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__init__.py +1 -0
  40. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/__init__.cpython-313.pyc +0 -0
  41. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/causes.cpython-313.pyc +0 -0
  42. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/correlate.cpython-313.pyc +0 -0
  43. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/events.cpython-313.pyc +0 -0
  44. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hangs.cpython-313.pyc +0 -0
  45. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hitches.cpython-313.pyc +0 -0
  46. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/summary.cpython-313.pyc +0 -0
  47. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/swiftui.cpython-313.pyc +0 -0
  48. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/time_profiler.cpython-313.pyc +0 -0
  49. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xctrace.cpython-313.pyc +0 -0
  50. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xml_utils.cpython-313.pyc +0 -0
  51. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/causes.py +187 -0
  52. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/correlate.py +179 -0
  53. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/events.py +291 -0
  54. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hangs.py +108 -0
  55. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hitches.py +145 -0
  56. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/summary.py +243 -0
  57. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/swiftui.py +195 -0
  58. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/time_profiler.py +135 -0
  59. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xctrace.py +117 -0
  60. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xml_utils.py +224 -0
  61. package/.local/skills/swiftui-expert-skill/scripts/record_trace.py +252 -0
  62. package/.local/skills/swiftui-liquid-glass/SKILL.md +90 -0
  63. package/.local/skills/swiftui-liquid-glass/agents/openai.yaml +4 -0
  64. package/.local/skills/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  65. package/.local/skills/swiftui-performance-audit/SKILL.md +106 -0
  66. package/.local/skills/swiftui-performance-audit/agents/openai.yaml +4 -0
  67. package/.local/skills/swiftui-performance-audit/references/code-smells.md +150 -0
  68. package/.local/skills/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  69. package/.local/skills/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  70. package/.local/skills/swiftui-performance-audit/references/profiling-intake.md +44 -0
  71. package/.local/skills/swiftui-performance-audit/references/report-template.md +47 -0
  72. package/.local/skills/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  73. package/.local/skills/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  74. package/.local/skills/swiftui-pro/SKILL.md +108 -0
  75. package/.local/skills/swiftui-pro/agents/openai.yaml +10 -0
  76. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  77. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  78. package/.local/skills/swiftui-pro/references/accessibility.md +13 -0
  79. package/.local/skills/swiftui-pro/references/api.md +39 -0
  80. package/.local/skills/swiftui-pro/references/data.md +43 -0
  81. package/.local/skills/swiftui-pro/references/design.md +32 -0
  82. package/.local/skills/swiftui-pro/references/hygiene.md +9 -0
  83. package/.local/skills/swiftui-pro/references/navigation.md +14 -0
  84. package/.local/skills/swiftui-pro/references/performance.md +46 -0
  85. package/.local/skills/swiftui-pro/references/swift.md +56 -0
  86. package/.local/skills/swiftui-pro/references/views.md +36 -0
  87. package/.local/skills/swiftui-ui-patterns/SKILL.md +95 -0
  88. package/.local/skills/swiftui-ui-patterns/agents/openai.yaml +4 -0
  89. package/.local/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  90. package/.local/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  91. package/.local/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  92. package/.local/skills/swiftui-ui-patterns/references/controls.md +57 -0
  93. package/.local/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  94. package/.local/skills/swiftui-ui-patterns/references/focus.md +90 -0
  95. package/.local/skills/swiftui-ui-patterns/references/form.md +97 -0
  96. package/.local/skills/swiftui-ui-patterns/references/grids.md +71 -0
  97. package/.local/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  98. package/.local/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  99. package/.local/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  100. package/.local/skills/swiftui-ui-patterns/references/list.md +86 -0
  101. package/.local/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  102. package/.local/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  103. package/.local/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  104. package/.local/skills/swiftui-ui-patterns/references/media.md +73 -0
  105. package/.local/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  106. package/.local/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  107. package/.local/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  108. package/.local/skills/swiftui-ui-patterns/references/performance.md +62 -0
  109. package/.local/skills/swiftui-ui-patterns/references/previews.md +48 -0
  110. package/.local/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  111. package/.local/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  112. package/.local/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  113. package/.local/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  114. package/.local/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  115. package/.local/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  116. package/.local/skills/swiftui-ui-patterns/references/theming.md +71 -0
  117. package/.local/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  118. package/.local/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
  119. package/.local/skills/swiftui-view-refactor/SKILL.md +202 -0
  120. package/.local/skills/swiftui-view-refactor/agents/openai.yaml +4 -0
  121. package/.local/skills/swiftui-view-refactor/references/mv-patterns.md +161 -0
  122. package/bundled/manifest.json +1 -1
  123. package/package.json +1 -1
@@ -0,0 +1,293 @@
1
+ # SwiftUI ScrollView Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [ScrollViewReader for Programmatic Scrolling](#scrollviewreader-for-programmatic-scrolling)
6
+ - [Scroll Position Tracking](#scroll-position-tracking)
7
+ - [Scroll Transitions and Effects](#scroll-transitions-and-effects)
8
+ - [Scroll Target Behavior](#scroll-target-behavior)
9
+ - [Summary Checklist](#summary-checklist)
10
+
11
+ ## ScrollViewReader for Programmatic Scrolling
12
+
13
+ **Use `ScrollViewReader` for scroll-to-top, scroll-to-bottom, and anchor-based jumps.**
14
+
15
+ ```swift
16
+ struct ChatView: View {
17
+ @State private var messages: [Message] = []
18
+ private let bottomID = "bottom"
19
+
20
+ var body: some View {
21
+ ScrollViewReader { proxy in
22
+ ScrollView {
23
+ LazyVStack {
24
+ ForEach(messages) { message in
25
+ MessageRow(message: message)
26
+ .id(message.id)
27
+ }
28
+ Color.clear
29
+ .frame(height: 1)
30
+ .id(bottomID)
31
+ }
32
+ }
33
+ .onChange(of: messages.count) { _, _ in
34
+ withAnimation {
35
+ proxy.scrollTo(bottomID, anchor: .bottom)
36
+ }
37
+ }
38
+ .onAppear {
39
+ proxy.scrollTo(bottomID, anchor: .bottom)
40
+ }
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Scroll-to-Top Pattern
47
+
48
+ ```swift
49
+ struct FeedView: View {
50
+ @State private var items: [Item] = []
51
+ @State private var scrollToTop = false
52
+ private let topID = "top"
53
+
54
+ var body: some View {
55
+ ScrollViewReader { proxy in
56
+ ScrollView {
57
+ LazyVStack {
58
+ Color.clear
59
+ .frame(height: 1)
60
+ .id(topID)
61
+
62
+ ForEach(items) { item in
63
+ ItemRow(item: item)
64
+ }
65
+ }
66
+ }
67
+ .onChange(of: scrollToTop) { _, shouldScroll in
68
+ if shouldScroll {
69
+ withAnimation {
70
+ proxy.scrollTo(topID, anchor: .top)
71
+ }
72
+ scrollToTop = false
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ **Why**: `ScrollViewReader` provides programmatic scroll control with stable anchors. Always use stable IDs and explicit animations.
81
+
82
+ ## Scroll Position Tracking
83
+
84
+ ### Basic Scroll Position
85
+
86
+ **Avoid** - Storing scroll position directly triggers view updates on every scroll frame:
87
+
88
+ ```swift
89
+ // ❌ Bad Practice - causes unnecessary re-renders
90
+ struct ContentView: View {
91
+ @State private var scrollPosition: CGFloat = 0
92
+
93
+ var body: some View {
94
+ ScrollView {
95
+ content
96
+ .background(
97
+ GeometryReader { geometry in
98
+ Color.clear
99
+ .preference(
100
+ key: ScrollOffsetPreferenceKey.self,
101
+ value: geometry.frame(in: .named("scroll")).minY
102
+ )
103
+ }
104
+ )
105
+ }
106
+ .coordinateSpace(name: "scroll")
107
+ .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
108
+ scrollPosition = value
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ **Preferred** - Check scroll position and update a flag based on thresholds for smoother, more efficient scrolling:
115
+
116
+ ```swift
117
+ // ✅ Good Practice - only updates state when crossing threshold
118
+ struct ContentView: View {
119
+ @State private var startAnimation: Bool = false
120
+
121
+ var body: some View {
122
+ ScrollView {
123
+ content
124
+ .background(
125
+ GeometryReader { geometry in
126
+ Color.clear
127
+ .preference(
128
+ key: ScrollOffsetPreferenceKey.self,
129
+ value: geometry.frame(in: .named("scroll")).minY
130
+ )
131
+ }
132
+ )
133
+ }
134
+ .coordinateSpace(name: "scroll")
135
+ .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
136
+ if value < -100 {
137
+ startAnimation = true
138
+ } else {
139
+ startAnimation = false
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ struct ScrollOffsetPreferenceKey: PreferenceKey {
146
+ static var defaultValue: CGFloat = 0
147
+ static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
148
+ value = nextValue()
149
+ }
150
+ }
151
+ ```
152
+
153
+ ### Scroll-Based Header Visibility
154
+
155
+ ```swift
156
+ struct ContentView: View {
157
+ @State private var showHeader = true
158
+
159
+ var body: some View {
160
+ VStack(spacing: 0) {
161
+ if showHeader {
162
+ HeaderView()
163
+ .transition(.move(edge: .top))
164
+ }
165
+
166
+ ScrollView {
167
+ content
168
+ .background(
169
+ GeometryReader { geometry in
170
+ Color.clear
171
+ .preference(
172
+ key: ScrollOffsetPreferenceKey.self,
173
+ value: geometry.frame(in: .named("scroll")).minY
174
+ )
175
+ }
176
+ )
177
+ }
178
+ .coordinateSpace(name: "scroll")
179
+ .onPreferenceChange(ScrollOffsetPreferenceKey.self) { offset in
180
+ if offset < -50 { // Scrolling down
181
+ withAnimation { showHeader = false }
182
+ } else if offset > 50 { // Scrolling up
183
+ withAnimation { showHeader = true }
184
+ }
185
+ }
186
+ }
187
+ }
188
+ }
189
+ ```
190
+
191
+ ## Scroll Transitions and Effects
192
+
193
+ > **iOS 17+**: All APIs in this section require iOS 17 or later.
194
+
195
+ ### Scroll-Based Opacity
196
+
197
+ ```swift
198
+ struct ParallaxView: View {
199
+ var body: some View {
200
+ ScrollView {
201
+ LazyVStack(spacing: 20) {
202
+ ForEach(items) { item in
203
+ ItemCard(item: item)
204
+ .visualEffect { content, geometry in
205
+ let frame = geometry.frame(in: .scrollView)
206
+ let distance = min(0, frame.minY)
207
+ return content
208
+ .opacity(1 + distance / 200)
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### Parallax Effect
218
+
219
+ ```swift
220
+ struct ParallaxHeader: View {
221
+ var body: some View {
222
+ ScrollView {
223
+ VStack(spacing: 0) {
224
+ Image("hero")
225
+ .resizable()
226
+ .aspectRatio(contentMode: .fill)
227
+ .frame(height: 300)
228
+ .visualEffect { content, geometry in
229
+ let offset = geometry.frame(in: .scrollView).minY
230
+ return content
231
+ .offset(y: offset > 0 ? -offset * 0.5 : 0)
232
+ }
233
+ .clipped()
234
+
235
+ ContentView()
236
+ }
237
+ }
238
+ }
239
+ }
240
+ ```
241
+
242
+ ## Scroll Target Behavior
243
+
244
+ > **iOS 17+**: All APIs in this section require iOS 17 or later.
245
+
246
+ ### Paging ScrollView
247
+
248
+ ```swift
249
+ struct PagingView: View {
250
+ var body: some View {
251
+ ScrollView(.horizontal) {
252
+ LazyHStack(spacing: 0) {
253
+ ForEach(pages) { page in
254
+ PageView(page: page)
255
+ .containerRelativeFrame(.horizontal)
256
+ }
257
+ }
258
+ .scrollTargetLayout()
259
+ }
260
+ .scrollTargetBehavior(.paging)
261
+ }
262
+ }
263
+ ```
264
+
265
+ ### Snap to Items
266
+
267
+ ```swift
268
+ struct SnapScrollView: View {
269
+ var body: some View {
270
+ ScrollView(.horizontal) {
271
+ LazyHStack(spacing: 16) {
272
+ ForEach(items) { item in
273
+ ItemCard(item: item)
274
+ .frame(width: 280)
275
+ }
276
+ }
277
+ .scrollTargetLayout()
278
+ }
279
+ .scrollTargetBehavior(.viewAligned)
280
+ .contentMargins(.horizontal, 20)
281
+ }
282
+ }
283
+ ```
284
+
285
+ ## Summary Checklist
286
+
287
+ - [ ] Use `ScrollViewReader` with stable IDs for programmatic scrolling
288
+ - [ ] Always use explicit animations with `scrollTo()`
289
+ - [ ] Use `.visualEffect` for scroll-based visual changes
290
+ - [ ] Use `.scrollTargetBehavior(.paging)` for paging behavior
291
+ - [ ] Use `.scrollTargetBehavior(.viewAligned)` for snap-to-item behavior
292
+ - [ ] Gate frequent scroll position updates by thresholds
293
+ - [ ] Use preference keys for custom scroll position tracking
@@ -0,0 +1,363 @@
1
+ # SwiftUI Sheet, Navigation & Inspector Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [Sheet Patterns](#sheet-patterns)
6
+ - [Navigation Patterns](#navigation-patterns)
7
+ - [Multi-Column Navigation with NavigationSplitView](#multi-column-navigation-with-navigationsplitview)
8
+ - [Inspector](#inspector)
9
+ - [Presentation Modifiers](#presentation-modifiers)
10
+ - [Summary Checklist](#summary-checklist)
11
+
12
+ ## Sheet Patterns
13
+
14
+ ### Item-Driven Sheets (Preferred)
15
+
16
+ **Use `.sheet(item:)` instead of `.sheet(isPresented:)` when presenting model-based content.**
17
+
18
+ ```swift
19
+ // Good - item-driven
20
+ @State private var selectedItem: Item?
21
+
22
+ var body: some View {
23
+ List(items) { item in
24
+ Button(item.name) {
25
+ selectedItem = item
26
+ }
27
+ }
28
+ .sheet(item: $selectedItem) { item in
29
+ ItemDetailSheet(item: item)
30
+ }
31
+ }
32
+
33
+ // Avoid - boolean flag requires separate state
34
+ @State private var showSheet = false
35
+ @State private var selectedItem: Item?
36
+
37
+ var body: some View {
38
+ List(items) { item in
39
+ Button(item.name) {
40
+ selectedItem = item
41
+ showSheet = true
42
+ }
43
+ }
44
+ .sheet(isPresented: $showSheet) {
45
+ if let selectedItem {
46
+ ItemDetailSheet(item: selectedItem)
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ **Why**: `.sheet(item:)` automatically handles presentation state and avoids optional unwrapping in the sheet body.
53
+
54
+ ### Sheets Own Their Actions
55
+
56
+ **Sheets should handle their own dismiss and actions internally** using `@Environment(\.dismiss)`. Avoid passing `onSave`/`onCancel` closures from the parent -- it creates callback prop-drilling and reduces reusability.
57
+
58
+ ```swift
59
+ struct EditItemSheet: View {
60
+ @Environment(\.dismiss) private var dismiss
61
+ let item: Item
62
+ @State private var name: String
63
+
64
+ init(item: Item) {
65
+ self.item = item
66
+ _name = State(initialValue: item.name)
67
+ }
68
+
69
+ var body: some View {
70
+ NavigationStack {
71
+ Form { TextField("Name", text: $name) }
72
+ .navigationTitle("Edit Item")
73
+ .toolbar {
74
+ ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } }
75
+ ToolbarItem(placement: .confirmationAction) { Button("Save") { /* save and dismiss */ } }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Enum-Based Sheet Management
83
+
84
+ When presenting multiple different sheets, use an `Identifiable` enum with `.sheet(item:)` instead of multiple boolean state properties:
85
+
86
+ ```swift
87
+ struct ArticlesView: View {
88
+ enum Sheet: Identifiable {
89
+ case add, edit(Article), categories
90
+ var id: String {
91
+ switch self {
92
+ case .add: "add"
93
+ case .edit(let a): "edit-\(a.id)"
94
+ case .categories: "categories"
95
+ }
96
+ }
97
+ }
98
+
99
+ @State private var presentedSheet: Sheet?
100
+
101
+ var body: some View {
102
+ List { /* ... */ }
103
+ .toolbar {
104
+ Button("Add") { presentedSheet = .add }
105
+ }
106
+ .sheet(item: $presentedSheet) { sheet in
107
+ switch sheet {
108
+ case .add: AddArticleView()
109
+ case .edit(let article): EditArticleView(article: article)
110
+ case .categories: CategoriesView()
111
+ }
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ **Why**: A single `@State` property and one `.sheet(item:)` modifier replaces N boolean properties and N sheet modifiers, improving readability and preventing only-one-sheet-at-a-time conflicts.
118
+
119
+ ## Navigation Patterns
120
+
121
+ ### Type-Safe Navigation with NavigationStack
122
+
123
+ ```swift
124
+ struct ContentView: View {
125
+ var body: some View {
126
+ NavigationStack {
127
+ List {
128
+ NavigationLink("Profile", value: Route.profile)
129
+ NavigationLink("Settings", value: Route.settings)
130
+ }
131
+ .navigationDestination(for: Route.self) { route in
132
+ switch route {
133
+ case .profile:
134
+ ProfileView()
135
+ case .settings:
136
+ SettingsView()
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ enum Route: Hashable {
144
+ case profile
145
+ case settings
146
+ }
147
+ ```
148
+
149
+ ### Programmatic Navigation
150
+
151
+ ```swift
152
+ struct ContentView: View {
153
+ @State private var navigationPath = NavigationPath()
154
+
155
+ var body: some View {
156
+ NavigationStack(path: $navigationPath) {
157
+ List {
158
+ Button("Go to Detail") {
159
+ navigationPath.append(DetailRoute.item(id: 1))
160
+ }
161
+ }
162
+ .navigationDestination(for: DetailRoute.self) { route in
163
+ switch route {
164
+ case .item(let id):
165
+ ItemDetailView(id: id)
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ enum DetailRoute: Hashable {
173
+ case item(id: Int)
174
+ }
175
+ ```
176
+
177
+ ## Multi-Column Navigation with NavigationSplitView
178
+
179
+ ### Two-Column Layout
180
+
181
+ Use `NavigationSplitView` for sidebar-driven navigation. Available on iOS 16+, macOS 13+, tvOS 16+, watchOS 9+.
182
+
183
+ ```swift
184
+ struct ContentView: View {
185
+ @State private var selectedItem: Item.ID?
186
+
187
+ var body: some View {
188
+ NavigationSplitView {
189
+ List(items, selection: $selectedItem) { item in
190
+ Text(item.name)
191
+ }
192
+ .navigationTitle("Items")
193
+ } detail: {
194
+ if let selectedItem, let item = items.first(where: { $0.id == selectedItem }) {
195
+ ItemDetailView(item: item)
196
+ } else {
197
+ ContentUnavailableView("Select an Item", systemImage: "doc")
198
+ }
199
+ }
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Three-Column Layout
205
+
206
+ ```swift
207
+ struct ContentView: View {
208
+ @State private var departmentId: Department.ID?
209
+ @State private var employeeIds = Set<Employee.ID>()
210
+
211
+ var body: some View {
212
+ NavigationSplitView {
213
+ List(model.departments, selection: $departmentId) { dept in
214
+ Text(dept.name)
215
+ }
216
+ } content: {
217
+ if let department = model.department(id: departmentId) {
218
+ List(department.employees, selection: $employeeIds) { emp in
219
+ Text(emp.name)
220
+ }
221
+ } else {
222
+ Text("Select a department")
223
+ }
224
+ } detail: {
225
+ EmployeeDetails(for: employeeIds)
226
+ }
227
+ }
228
+ }
229
+ ```
230
+
231
+ ### Configuration
232
+
233
+ - **Column visibility**: `NavigationSplitView(columnVisibility: $visibility)` with `NavigationSplitViewVisibility` (`.detailOnly`, `.doubleColumn`, `.all`)
234
+ - **Column widths**: `.navigationSplitViewColumnWidth(min:ideal:max:)` on each column
235
+ - **Compact column**: `NavigationSplitView(preferredCompactColumn: $column)` to control which column shows on narrow devices
236
+ - **Style**: `.navigationSplitViewStyle(.balanced)` or `.prominentDetail` (default)
237
+
238
+ ### Platform Behavior
239
+
240
+ | Platform | Behavior |
241
+ |----------|----------|
242
+ | **macOS** | Columns always visible side-by-side; sidebar has translucent material; variable-width column resizing by dragging |
243
+ | **iPadOS (regular)** | Sidebar can overlay or push detail; supports column visibility toggle via toolbar button |
244
+ | **iOS / iPadOS (compact)** | Collapses into a single `NavigationStack`; sidebar items show disclosure chevrons; back button navigates between columns |
245
+ | **iPhone (all sizes)** | Always collapsed into a stack; sidebar appears as the root list; selections push detail onto the stack |
246
+ | **watchOS / tvOS** | Collapses into a single stack |
247
+
248
+ ## Inspector
249
+
250
+ > **Availability:** iOS 17.0+, macOS 14.0+
251
+
252
+ A trailing-edge panel for supplementary information.
253
+
254
+ On wider size classes (macOS, iPad landscape), it appears as a **trailing column**. On compact size classes (iPhone), it **adapts to a sheet** automatically.
255
+
256
+ ### Basic Inspector
257
+
258
+ ```swift
259
+ struct ShapeEditor: View {
260
+ @State private var showInspector = false
261
+
262
+ var body: some View {
263
+ MyEditorView()
264
+ .inspector(isPresented: $showInspector) {
265
+ InspectorContent()
266
+ }
267
+ .toolbar {
268
+ ToolbarItem {
269
+ Button {
270
+ showInspector.toggle()
271
+ } label: {
272
+ Label("Inspector", systemImage: "info.circle")
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### Inspector with Column Width
281
+
282
+ ```swift
283
+ MyEditorView()
284
+ .inspector(isPresented: $showInspector) {
285
+ InspectorContent()
286
+ .inspectorColumnWidth(min: 200, ideal: 250, max: 400)
287
+ }
288
+ ```
289
+
290
+ ### Inspector with Fixed Width
291
+
292
+ ```swift
293
+ MyEditorView()
294
+ .inspector(isPresented: $showInspector) {
295
+ InspectorContent()
296
+ .inspectorColumnWidth(300)
297
+ }
298
+ ```
299
+
300
+ ### Platform Behavior
301
+
302
+ | Platform | Behavior |
303
+ |----------|----------|
304
+ | **macOS** | Trailing-edge sidebar panel; resizable by dragging edge; integrates with window toolbar |
305
+ | **iPadOS (regular)** | Trailing column alongside content; toggleable via toolbar button |
306
+ | **iOS / iPadOS (compact)** | Adapts to a sheet presentation; swipe-to-dismiss supported |
307
+ | **iPhone (all sizes)** | Always presented as a sheet (no trailing column); dismiss via swipe or button |
308
+
309
+ > **Tip:** Use `InspectorCommands` in your app's `.commands` to include the default inspector toggle keyboard shortcut.
310
+
311
+ ## Presentation Modifiers
312
+
313
+ ### Full Screen Cover
314
+
315
+ ```swift
316
+ struct ContentView: View {
317
+ @State private var showFullScreen = false
318
+
319
+ var body: some View {
320
+ Button("Show Full Screen") {
321
+ showFullScreen = true
322
+ }
323
+ .fullScreenCover(isPresented: $showFullScreen) {
324
+ FullScreenView()
325
+ }
326
+ }
327
+ }
328
+ ```
329
+
330
+ ### Popover
331
+
332
+ ```swift
333
+ struct ContentView: View {
334
+ @State private var showPopover = false
335
+
336
+ var body: some View {
337
+ Button("Show Popover") {
338
+ showPopover = true
339
+ }
340
+ .popover(isPresented: $showPopover) {
341
+ PopoverContentView()
342
+ .presentationCompactAdaptation(.popover) // Don't adapt to sheet on iPhone
343
+ }
344
+ }
345
+ }
346
+ ```
347
+
348
+ For `alert` and `confirmationDialog` API patterns, see `latest-apis.md`.
349
+
350
+ ## Summary Checklist
351
+
352
+ - [ ] Use `.sheet(item:)` for model-based sheets
353
+ - [ ] Sheets own their actions and dismiss internally
354
+ - [ ] Use `NavigationStack` with `navigationDestination(for:)` for type-safe navigation
355
+ - [ ] Use `NavigationPath` for programmatic navigation
356
+ - [ ] Use `NavigationSplitView` for sidebar-driven multi-column layouts
357
+ - [ ] Use `Inspector` for trailing-edge supplementary panels
358
+ - [ ] Set column widths with `navigationSplitViewColumnWidth(min:ideal:max:)` or `inspectorColumnWidth(min:ideal:max:)`
359
+ - [ ] Use appropriate presentation modifiers (sheet, fullScreenCover, popover)
360
+ - [ ] Alerts and confirmation dialogs use modern API with actions
361
+ - [ ] Avoid passing dismiss/save callbacks to sheets
362
+ - [ ] Use enum-based `Identifiable` type with `.sheet(item:)` when presenting multiple sheets
363
+ - [ ] Navigation state can be saved/restored when needed