claudecode-omc 5.6.6 → 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 (179) 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/h5-to-swiftui/SKILL.md +201 -0
  6. package/.local/skills/h5-to-swiftui/assets/calibration/README.md +176 -0
  7. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/index.html +52 -0
  8. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/style.css +133 -0
  9. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Package.swift +26 -0
  10. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Sources/CalibrationScreen/CalibrationScreen.swift +142 -0
  11. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Package.swift +32 -0
  12. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Sources/CalibrationScreenDivergent/CalibrationScreenDivergent.swift +122 -0
  13. package/.local/skills/h5-to-swiftui/assets/calibration/tokens.json +42 -0
  14. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/index.html +14 -0
  15. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/package.json +20 -0
  16. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/001.json +96 -0
  17. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/index.json +89 -0
  18. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.jsx +22 -0
  19. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.module.css +11 -0
  20. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.jsx +53 -0
  21. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.module.css +139 -0
  22. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.jsx +37 -0
  23. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.module.css +72 -0
  24. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.jsx +30 -0
  25. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.module.css +50 -0
  26. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.jsx +159 -0
  27. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.module.css +21 -0
  28. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/main.jsx +12 -0
  29. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.jsx +182 -0
  30. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.module.css +294 -0
  31. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.jsx +147 -0
  32. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.module.css +161 -0
  33. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/global.css +50 -0
  34. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/tokens.css +103 -0
  35. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/vite.config.js +6 -0
  36. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/data/tasks.js +67 -0
  37. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/index.html +26 -0
  38. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/router.js +73 -0
  39. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/detail.js +164 -0
  40. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/home.js +53 -0
  41. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/list.js +87 -0
  42. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/app.css +342 -0
  43. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/tokens.css +68 -0
  44. package/.local/skills/h5-to-swiftui/references/css-to-swiftui-map.md +205 -0
  45. package/.local/skills/h5-to-swiftui/references/design-token-extraction.md +209 -0
  46. package/.local/skills/h5-to-swiftui/references/high-risk-triage.md +209 -0
  47. package/.local/skills/h5-to-swiftui/references/render-equivalence-calibration.md +193 -0
  48. package/.local/skills/h5-to-swiftui/references/stack-detection.md +160 -0
  49. package/.local/skills/h5-to-swiftui/references/visual-diff-loop-protocol.md +365 -0
  50. package/.local/skills/h5-to-swiftui/scripts/_calib-consts.mjs +150 -0
  51. package/.local/skills/h5-to-swiftui/scripts/_imglib.mjs +547 -0
  52. package/.local/skills/h5-to-swiftui/scripts/_provenance.mjs +123 -0
  53. package/.local/skills/h5-to-swiftui/scripts/calibrate-render.mjs +625 -0
  54. package/.local/skills/h5-to-swiftui/scripts/capture-reference.mjs +386 -0
  55. package/.local/skills/h5-to-swiftui/scripts/detect-stack.mjs +305 -0
  56. package/.local/skills/h5-to-swiftui/scripts/evaluate-convergence.mjs +1093 -0
  57. package/.local/skills/h5-to-swiftui/scripts/extract-tokens.mjs +600 -0
  58. package/.local/skills/h5-to-swiftui/scripts/mark-overlay.mjs +379 -0
  59. package/.local/skills/h5-to-swiftui/scripts/pixel-diff.mjs +530 -0
  60. package/.local/skills/h5-to-swiftui/scripts/sim-screenshot.sh +544 -0
  61. package/.local/skills/ios-debugger-agent/SKILL.md +51 -0
  62. package/.local/skills/ios-debugger-agent/agents/openai.yaml +4 -0
  63. package/.local/skills/swift-concurrency-expert/SKILL.md +105 -0
  64. package/.local/skills/swift-concurrency-expert/agents/openai.yaml +4 -0
  65. package/.local/skills/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
  66. package/.local/skills/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
  67. package/.local/skills/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
  68. package/.local/skills/swiftui-expert-skill/SKILL.md +162 -0
  69. package/.local/skills/swiftui-expert-skill/references/accessibility-patterns.md +215 -0
  70. package/.local/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  71. package/.local/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  72. package/.local/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  73. package/.local/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  74. package/.local/skills/swiftui-expert-skill/references/charts.md +602 -0
  75. package/.local/skills/swiftui-expert-skill/references/focus-patterns.md +299 -0
  76. package/.local/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  77. package/.local/skills/swiftui-expert-skill/references/latest-apis.md +488 -0
  78. package/.local/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  79. package/.local/skills/swiftui-expert-skill/references/liquid-glass.md +423 -0
  80. package/.local/skills/swiftui-expert-skill/references/list-patterns.md +446 -0
  81. package/.local/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  82. package/.local/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  83. package/.local/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  84. package/.local/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  85. package/.local/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  86. package/.local/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  87. package/.local/skills/swiftui-expert-skill/references/state-management.md +388 -0
  88. package/.local/skills/swiftui-expert-skill/references/text-patterns.md +32 -0
  89. package/.local/skills/swiftui-expert-skill/references/trace-analysis.md +295 -0
  90. package/.local/skills/swiftui-expert-skill/references/trace-recording.md +134 -0
  91. package/.local/skills/swiftui-expert-skill/references/view-structure.md +780 -0
  92. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/analyze_trace.cpython-313.pyc +0 -0
  93. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/record_trace.cpython-313.pyc +0 -0
  94. package/.local/skills/swiftui-expert-skill/scripts/analyze_trace.py +301 -0
  95. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__init__.py +1 -0
  96. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/__init__.cpython-313.pyc +0 -0
  97. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/causes.cpython-313.pyc +0 -0
  98. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/correlate.cpython-313.pyc +0 -0
  99. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/events.cpython-313.pyc +0 -0
  100. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hangs.cpython-313.pyc +0 -0
  101. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hitches.cpython-313.pyc +0 -0
  102. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/summary.cpython-313.pyc +0 -0
  103. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/swiftui.cpython-313.pyc +0 -0
  104. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/time_profiler.cpython-313.pyc +0 -0
  105. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xctrace.cpython-313.pyc +0 -0
  106. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xml_utils.cpython-313.pyc +0 -0
  107. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/causes.py +187 -0
  108. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/correlate.py +179 -0
  109. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/events.py +291 -0
  110. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hangs.py +108 -0
  111. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hitches.py +145 -0
  112. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/summary.py +243 -0
  113. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/swiftui.py +195 -0
  114. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/time_profiler.py +135 -0
  115. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xctrace.py +117 -0
  116. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xml_utils.py +224 -0
  117. package/.local/skills/swiftui-expert-skill/scripts/record_trace.py +252 -0
  118. package/.local/skills/swiftui-liquid-glass/SKILL.md +90 -0
  119. package/.local/skills/swiftui-liquid-glass/agents/openai.yaml +4 -0
  120. package/.local/skills/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  121. package/.local/skills/swiftui-performance-audit/SKILL.md +106 -0
  122. package/.local/skills/swiftui-performance-audit/agents/openai.yaml +4 -0
  123. package/.local/skills/swiftui-performance-audit/references/code-smells.md +150 -0
  124. package/.local/skills/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  125. package/.local/skills/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  126. package/.local/skills/swiftui-performance-audit/references/profiling-intake.md +44 -0
  127. package/.local/skills/swiftui-performance-audit/references/report-template.md +47 -0
  128. package/.local/skills/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  129. package/.local/skills/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  130. package/.local/skills/swiftui-pro/SKILL.md +108 -0
  131. package/.local/skills/swiftui-pro/agents/openai.yaml +10 -0
  132. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  133. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  134. package/.local/skills/swiftui-pro/references/accessibility.md +13 -0
  135. package/.local/skills/swiftui-pro/references/api.md +39 -0
  136. package/.local/skills/swiftui-pro/references/data.md +43 -0
  137. package/.local/skills/swiftui-pro/references/design.md +32 -0
  138. package/.local/skills/swiftui-pro/references/hygiene.md +9 -0
  139. package/.local/skills/swiftui-pro/references/navigation.md +14 -0
  140. package/.local/skills/swiftui-pro/references/performance.md +46 -0
  141. package/.local/skills/swiftui-pro/references/swift.md +56 -0
  142. package/.local/skills/swiftui-pro/references/views.md +36 -0
  143. package/.local/skills/swiftui-ui-patterns/SKILL.md +95 -0
  144. package/.local/skills/swiftui-ui-patterns/agents/openai.yaml +4 -0
  145. package/.local/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  146. package/.local/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  147. package/.local/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  148. package/.local/skills/swiftui-ui-patterns/references/controls.md +57 -0
  149. package/.local/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  150. package/.local/skills/swiftui-ui-patterns/references/focus.md +90 -0
  151. package/.local/skills/swiftui-ui-patterns/references/form.md +97 -0
  152. package/.local/skills/swiftui-ui-patterns/references/grids.md +71 -0
  153. package/.local/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  154. package/.local/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  155. package/.local/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  156. package/.local/skills/swiftui-ui-patterns/references/list.md +86 -0
  157. package/.local/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  158. package/.local/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  159. package/.local/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  160. package/.local/skills/swiftui-ui-patterns/references/media.md +73 -0
  161. package/.local/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  162. package/.local/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  163. package/.local/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  164. package/.local/skills/swiftui-ui-patterns/references/performance.md +62 -0
  165. package/.local/skills/swiftui-ui-patterns/references/previews.md +48 -0
  166. package/.local/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  167. package/.local/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  168. package/.local/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  169. package/.local/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  170. package/.local/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  171. package/.local/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  172. package/.local/skills/swiftui-ui-patterns/references/theming.md +71 -0
  173. package/.local/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  174. package/.local/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
  175. package/.local/skills/swiftui-view-refactor/SKILL.md +202 -0
  176. package/.local/skills/swiftui-view-refactor/agents/openai.yaml +4 -0
  177. package/.local/skills/swiftui-view-refactor/references/mv-patterns.md +161 -0
  178. package/bundled/manifest.json +1 -1
  179. package/package.json +1 -1
@@ -0,0 +1,303 @@
1
+ # macOS Window & Toolbar Styling Reference
2
+
3
+ > Window configuration, toolbar styles, sizing, positioning, and navigation patterns specific to macOS SwiftUI apps.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Quick Lookup Table](#quick-lookup-table)
8
+ - [Toolbar Styles](#toolbar-styles)
9
+ - [Window Style](#window-style)
10
+ - [Window Sizing](#window-sizing)
11
+ - [MenuBarExtra Style (macOS-only)](#menubarextra-style-macos-only)
12
+ - [Navigation Layout (macOS behavior)](#navigation-layout-macos-behavior)
13
+ - [Commands & Keyboard](#commands--keyboard)
14
+ - [Best Practices](#best-practices)
15
+
16
+ ---
17
+
18
+ ## Quick Lookup Table
19
+
20
+ | API | Availability | macOS-Only? | Usage |
21
+ |-----|-------------|:-----------:|-------|
22
+ | `windowToolbarStyle(_:)` | macOS 11.0+ | Yes | Sets toolbar style: `.unified`, `.unifiedCompact`, `.expanded` |
23
+ | `windowStyle(_:)` | macOS 11.0+ | No | Supports `.hiddenTitleBar` for chromeless windows |
24
+ | `windowResizability(_:)` | macOS 13.0+ | No | Controls resize handle and green zoom button behavior |
25
+ | `defaultSize(width:height:)` | macOS 13.0+ | No | Initial frame size when user creates a new window |
26
+ | `defaultPosition(_:)` | macOS 13.0+ | No | Initial window position on screen |
27
+ | `windowIdealPlacement(_:)` | macOS 15.0+ | No | Closure with display geometry for precise window positioning |
28
+ | `menuBarExtraStyle(_:)` | macOS 13.0+ | Yes | Sets MenuBarExtra to `.menu` or `.window` style |
29
+ | `NavigationSplitView` | macOS 13.0+ | No | Columns always visible side-by-side on macOS; translucent sidebar |
30
+ | `Inspector` | macOS 14.0+ | No | Trailing-edge sidebar panel; resizable by dragging |
31
+
32
+ ---
33
+
34
+ ## Toolbar Styles
35
+
36
+ ### windowToolbarStyle (macOS-only)
37
+
38
+ Controls how the toolbar and title bar are displayed. Applied to a scene.
39
+
40
+ ```swift
41
+ @main
42
+ struct MyApp: App {
43
+ var body: some Scene {
44
+ WindowGroup {
45
+ ContentView()
46
+ }
47
+ // Title bar and toolbar in a single row
48
+ .windowToolbarStyle(.unified)
49
+ }
50
+ }
51
+ ```
52
+
53
+ **Available styles:**
54
+
55
+ | Style | Description |
56
+ |-------|-------------|
57
+ | `.automatic` | System default |
58
+ | `.unified` | Title bar and toolbar in a single combined row |
59
+ | `.unifiedCompact` | Same as unified but with reduced vertical height |
60
+ | `.expanded` | Title bar displayed above the toolbar (more toolbar space) |
61
+
62
+ ```swift
63
+ // Unified compact — minimal chrome
64
+ .windowToolbarStyle(.unifiedCompact)
65
+
66
+ // Expanded — title bar above toolbar
67
+ .windowToolbarStyle(.expanded)
68
+
69
+ // Unified with title hidden
70
+ .windowToolbarStyle(.unified(showsTitle: false))
71
+ ```
72
+
73
+ ### Toolbar content
74
+
75
+ ```swift
76
+ struct ContentView: View {
77
+ @State private var searchText = ""
78
+
79
+ var body: some View {
80
+ NavigationSplitView {
81
+ SidebarView()
82
+ } detail: {
83
+ DetailView()
84
+ }
85
+ .toolbar {
86
+ ToolbarItem(placement: .automatic) {
87
+ Button(action: addItem) {
88
+ Label("Add", systemImage: "plus")
89
+ }
90
+ }
91
+ }
92
+ .searchable(text: $searchText, placement: .sidebar)
93
+ }
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Window Style
100
+
101
+ ### windowStyle
102
+
103
+ Set the visual style of a window. Use `.hiddenTitleBar` for chromeless, immersive windows.
104
+
105
+ ```swift
106
+ // Standard title bar (default)
107
+ WindowGroup {
108
+ ContentView()
109
+ }
110
+ .windowStyle(.titleBar)
111
+
112
+ // Hidden title bar — chromeless window
113
+ WindowGroup {
114
+ ContentView()
115
+ }
116
+ .windowStyle(.hiddenTitleBar)
117
+ ```
118
+
119
+ > **Use case:** `.hiddenTitleBar` is useful for media players, custom-chrome apps, or immersive experiences where the standard title bar is unwanted.
120
+
121
+ ---
122
+
123
+ ## Window Sizing
124
+
125
+ ### windowResizability, defaultSize, defaultPosition
126
+
127
+ These modifiers work together to configure window sizing and placement:
128
+
129
+ ```swift
130
+ WindowGroup {
131
+ ContentView()
132
+ .frame(minWidth: 600, minHeight: 400)
133
+ }
134
+ .defaultSize(width: 900, height: 600)
135
+ .defaultPosition(.center)
136
+ .windowResizability(.contentMinSize)
137
+ ```
138
+
139
+ **`windowResizability` options:**
140
+
141
+ | Value | Behavior |
142
+ |-------|----------|
143
+ | `.automatic` | System decides resize behavior |
144
+ | `.contentSize` | Fixed to content size; no user resize; zoom button disabled |
145
+ | `.contentMinSize` | Resizable with minimum based on content's `minWidth`/`minHeight` |
146
+
147
+ **`defaultPosition` options:** `.center`, `.topLeading`, `.top`, `.topTrailing`, `.leading`, `.trailing`, `.bottomLeading`, `.bottom`, `.bottomTrailing`
148
+
149
+ **Guidelines:**
150
+ - Set `minWidth`/`minHeight` via `.frame()` on content, enforce with `.contentMinSize`
151
+ - Use `.defaultSize()` for initial dimensions (larger than minimums)
152
+ - `defaultSize` also accepts `CGSize`
153
+
154
+ ### windowIdealPlacement (macOS 15.0+)
155
+
156
+ For precise programmatic positioning, use a closure with display geometry:
157
+
158
+ ```swift
159
+ .windowIdealPlacement { context in
160
+ let screen = context.defaultDisplay.visibleArea
161
+ return WindowPlacement(x: screen.midX, y: screen.midY,
162
+ width: screen.width / 2, height: screen.height)
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ## MenuBarExtra Style (macOS-only)
169
+
170
+ Choose between dropdown menu and popover panel for `MenuBarExtra`.
171
+
172
+ ```swift
173
+ // Dropdown menu (default)
174
+ MenuBarExtra("Status", systemImage: "chart.bar") {
175
+ Button("Action") { /* ... */ }
176
+ }
177
+ .menuBarExtraStyle(.menu)
178
+
179
+ // Popover panel with custom SwiftUI content
180
+ MenuBarExtra("Status", systemImage: "chart.bar") {
181
+ DashboardView()
182
+ }
183
+ .menuBarExtraStyle(.window)
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Navigation Layout (macOS behavior)
189
+
190
+ ### NavigationSplitView
191
+
192
+ On macOS, `NavigationSplitView` displays columns side-by-side (never overlaid). The sidebar gets a translucent material background. Columns support variable-width resizing by the user.
193
+
194
+ ```swift
195
+ NavigationSplitView {
196
+ List(items, selection: $selectedId) { item in
197
+ Text(item.name)
198
+ }
199
+ .navigationSplitViewColumnWidth(min: 180, ideal: 220, max: 300)
200
+ } detail: {
201
+ DetailView(id: selectedId)
202
+ }
203
+ .navigationSplitViewStyle(.balanced)
204
+ ```
205
+
206
+ Use the three-column variant (`sidebar` / `content` / `detail`) for master-detail-detail layouts. Customize column widths with `.navigationSplitViewColumnWidth(min:ideal:max:)`.
207
+
208
+ ### Inspector (macOS 14.0+)
209
+
210
+ A trailing-edge panel for supplementary information. On macOS, it appears as a sidebar-style panel that can be resized by dragging its edge.
211
+
212
+ ```swift
213
+ struct ContentView: View {
214
+ @State private var showInspector = false
215
+
216
+ var body: some View {
217
+ MainContent()
218
+ .inspector(isPresented: $showInspector) {
219
+ InspectorView()
220
+ .inspectorColumnWidth(min: 200, ideal: 250, max: 400)
221
+ }
222
+ .toolbar {
223
+ ToolbarItem {
224
+ Button {
225
+ showInspector.toggle()
226
+ } label: {
227
+ Label("Inspector", systemImage: "info.circle")
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Commands & Keyboard
238
+
239
+ ### Commands, CommandGroup, CommandMenu
240
+
241
+ Define menu bar commands. On macOS, these populate the menu bar directly. On iOS, they create key commands.
242
+
243
+ ```swift
244
+ .commands {
245
+ CommandMenu("Tools") {
246
+ Button("Run Analysis") { /* ... */ }
247
+ .keyboardShortcut("r", modifiers: [.command, .shift])
248
+ }
249
+ CommandGroup(after: .newItem) {
250
+ Button("New From Template...") { /* ... */ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ **`CommandGroup` placement options:** `.replacing(_:)` replaces a system group, `.before(_:)` / `.after(_:)` inserts adjacent to it. Common placements: `.newItem`, `.saveItem`, `.help`, `.toolbar`, `.sidebar`.
256
+
257
+ ### KeyboardShortcut
258
+
259
+ On macOS, shortcuts are displayed alongside menu items and in button tooltips on hover.
260
+
261
+ ```swift
262
+ Button("Save") {
263
+ save()
264
+ }
265
+ .keyboardShortcut("s", modifiers: .command)
266
+
267
+ Button("Delete") {
268
+ delete()
269
+ }
270
+ .keyboardShortcut(.delete, modifiers: .command)
271
+ ```
272
+
273
+ ### openWindow
274
+
275
+ Programmatically open a window. If the target window is already open, brings it to the front.
276
+
277
+ ```swift
278
+ struct ToolbarActions: View {
279
+ @Environment(\.openWindow) private var openWindow
280
+
281
+ var body: some View {
282
+ Button("Connection Doctor") {
283
+ openWindow(id: "connection-doctor")
284
+ }
285
+
286
+ Button("Show Message") {
287
+ openWindow(value: message.id) // Type-matched to WindowGroup
288
+ }
289
+ }
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Best Practices
296
+
297
+ - **Use `.unified` or `.unifiedCompact`** for most apps — `.expanded` only when you need many toolbar items
298
+ - **Set min frame sizes on content** and use `.windowResizability(.contentMinSize)` to enforce them
299
+ - **Always provide `defaultSize`** so new windows start at a reasonable size
300
+ - **Use `NavigationSplitView`** for sidebar navigation — not `HSplitView`
301
+ - **Use `Inspector`** for supplementary panels — it integrates with the toolbar automatically
302
+ - **Define `Commands`** for all repeatable actions — users expect keyboard shortcuts on macOS
303
+ - **Use `#if os(macOS)`** to wrap macOS-only window configuration in multiplatform projects
@@ -0,0 +1,403 @@
1
+ # SwiftUI Performance Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [Performance Optimization](#performance-optimization)
6
+ - [Anti-Patterns](#anti-patterns)
7
+ - [Summary Checklist](#summary-checklist)
8
+
9
+ ## Performance Optimization
10
+
11
+ ### 1. Avoid Redundant State Updates
12
+
13
+ SwiftUI doesn't compare values before triggering updates:
14
+
15
+ ```swift
16
+ // BAD - triggers update even if value unchanged
17
+ .onReceive(publisher) { value in
18
+ self.currentValue = value // Always triggers body re-evaluation
19
+ }
20
+
21
+ // GOOD - only update when different
22
+ .onReceive(publisher) { value in
23
+ if self.currentValue != value {
24
+ self.currentValue = value
25
+ }
26
+ }
27
+ ```
28
+
29
+ ### 2. Optimize Hot Paths
30
+
31
+ Hot paths are frequently executed code (scroll handlers, animations, gestures):
32
+
33
+ ```swift
34
+ // BAD - updates state on every scroll position change
35
+ .onPreferenceChange(ScrollOffsetKey.self) { offset in
36
+ shouldShowTitle = offset.y <= -32 // Fires constantly during scroll!
37
+ }
38
+
39
+ // GOOD - only update when threshold crossed
40
+ .onPreferenceChange(ScrollOffsetKey.self) { offset in
41
+ let shouldShow = offset.y <= -32
42
+ if shouldShow != shouldShowTitle {
43
+ shouldShowTitle = shouldShow // Fires only when crossing threshold
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### 3. Pass Only What Views Need
49
+
50
+ **Avoid passing large "config" or "context" objects.** Pass only the specific values each view needs.
51
+
52
+ ```swift
53
+ // Good - pass specific values
54
+ ThemeSelector(theme: config.theme)
55
+ FontSizeSlider(fontSize: config.fontSize)
56
+
57
+ // Avoid - passing entire config (creates broad dependency)
58
+ ThemeSelector(config: config) // Notified of ALL config changes
59
+ ```
60
+
61
+ With `ObservableObject`, any `@Published` change triggers all observers. With `@Observable`, views update only when accessed properties change, but passing entire objects still creates broader dependencies than necessary.
62
+
63
+ ### 4. Use Equatable Views
64
+
65
+ For views with expensive bodies, conform to `Equatable`:
66
+
67
+ ```swift
68
+ struct ExpensiveView: View, Equatable {
69
+ let data: SomeData
70
+
71
+ static func == (lhs: Self, rhs: Self) -> Bool {
72
+ lhs.data.id == rhs.data.id // Custom equality check
73
+ }
74
+
75
+ var body: some View {
76
+ // Expensive computation
77
+ }
78
+ }
79
+
80
+ // Usage
81
+ ExpensiveView(data: data)
82
+ .equatable() // Use custom equality
83
+ ```
84
+
85
+ **Caution**: If you add new state or dependencies to your view, remember to update your `==` function!
86
+
87
+ ### 5. POD Views for Fast Diffing
88
+
89
+ **POD (Plain Old Data) views use `memcmp` for fastest diffing.** A view is POD if it only contains simple value types and no property wrappers.
90
+
91
+ ```swift
92
+ // POD view - fastest diffing
93
+ struct FastView: View {
94
+ let title: String
95
+ let count: Int
96
+
97
+ var body: some View {
98
+ Text("\(title): \(count)")
99
+ }
100
+ }
101
+
102
+ // Non-POD view - uses reflection or custom equality
103
+ struct SlowerView: View {
104
+ let title: String
105
+ @State private var isExpanded = false // Property wrapper makes it non-POD
106
+
107
+ var body: some View {
108
+ Text(title)
109
+ }
110
+ }
111
+ ```
112
+
113
+ **Advanced Pattern**: Wrap expensive non-POD views in POD parent views:
114
+
115
+ ```swift
116
+ // POD wrapper for fast diffing
117
+ struct ExpensiveView: View {
118
+ let value: Int
119
+
120
+ var body: some View {
121
+ ExpensiveViewInternal(value: value)
122
+ }
123
+ }
124
+
125
+ // Internal view with state
126
+ private struct ExpensiveViewInternal: View {
127
+ let value: Int
128
+ @State private var item: Item?
129
+
130
+ var body: some View {
131
+ // Expensive rendering
132
+ }
133
+ }
134
+ ```
135
+
136
+ **Why**: The POD parent uses fast `memcmp` comparison. Only when `value` changes does the internal view get diffed.
137
+
138
+ ### 6. Lazy Loading
139
+
140
+ Use lazy containers for large collections:
141
+
142
+ ```swift
143
+ // BAD - creates all views immediately
144
+ ScrollView {
145
+ VStack {
146
+ ForEach(items) { item in
147
+ ExpensiveRow(item: item)
148
+ }
149
+ }
150
+ }
151
+
152
+ // GOOD - creates views on demand
153
+ ScrollView {
154
+ LazyVStack {
155
+ ForEach(items) { item in
156
+ ExpensiveRow(item: item)
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ **iOS 26+ note**: Nested scroll views containing lazy stacks now automatically defer loading their children until they are about to appear, matching the behavior of top-level lazy stacks. This benefits patterns like horizontal photo carousels inside a vertical scroll view.
163
+
164
+ > Source: "What's new in SwiftUI" (WWDC25, session 256)
165
+
166
+ ### 7. Task Cancellation
167
+
168
+ Cancel async work when view disappears:
169
+
170
+ ```swift
171
+ struct DataView: View {
172
+ @State private var data: [Item] = []
173
+
174
+ var body: some View {
175
+ List(data) { item in
176
+ Text(item.name)
177
+ }
178
+ .task {
179
+ // Automatically cancelled when view disappears
180
+ data = await fetchData()
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### 8. Debug View Updates
187
+
188
+ **Use `Self._printChanges()` or `Self._logChanges()` to debug unexpected view updates.**
189
+
190
+ ```swift
191
+ struct DebugView: View {
192
+ @State private var count = 0
193
+ @State private var name = ""
194
+
195
+ var body: some View {
196
+ #if DEBUG
197
+ let _ = Self._logChanges() // Xcode 15.1+: logs to com.apple.SwiftUI subsystem
198
+ #endif
199
+
200
+ VStack {
201
+ Text("Count: \(count)")
202
+ Text("Name: \(name)")
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ - `Self._printChanges()`: Prints which properties changed to standard output.
209
+ - `Self._logChanges()` (iOS 17+): Logs to the `com.apple.SwiftUI` subsystem with category "Changed Body Properties", using `os_log` for structured output.
210
+
211
+ Both print `@self` when the view value itself changed and `@identity` when the view's persistent data was recycled.
212
+
213
+ **Why**: This helps identify which state changes are causing view updates. Isolating redraw triggers into single-responsibility subviews is often the fix -- extracting a subview means SwiftUI can skip its body when its inputs haven't changed.
214
+
215
+ ### 9. Eliminate Unnecessary Dependencies
216
+
217
+ **Narrow state scope to reduce update fan-out.** Instead of passing an entire `@Observable` model to a row view (which creates a dependency on all accessed properties), pass only the specific values the view needs as `let` properties.
218
+
219
+ ```swift
220
+ // Bad - broad dependency on entire model
221
+ struct ItemRow: View {
222
+ @Environment(AppModel.self) private var model
223
+ let item: Item
224
+ var body: some View { Text(item.name).foregroundStyle(model.theme.primaryColor) }
225
+ }
226
+
227
+ // Good - narrow dependency
228
+ struct ItemRow: View {
229
+ let item: Item
230
+ let themeColor: Color
231
+ var body: some View { Text(item.name).foregroundStyle(themeColor) }
232
+ }
233
+ ```
234
+
235
+ **Avoid storing frequently-changing values in the environment.** Even when a view doesn't read the changed key, SwiftUI still checks all environment readers. This cost adds up with many views and frequent updates (geometry values, timers).
236
+
237
+ > Source: "Optimize SwiftUI performance with Instruments" (WWDC25, session 306)
238
+
239
+ ### 10. @Observable Dependency Granularity
240
+
241
+ **Consider per-item `@Observable` state holders (one per row/item) to narrow update scope.** When multiple list items share a dependency on the same `@Observable` array, changing one element causes all items to re-evaluate their bodies.
242
+
243
+ ```swift
244
+ // BAD - all item views depend on the full favorites array
245
+ @Observable
246
+ class ModelData {
247
+ var favorites: [Landmark] = []
248
+
249
+ func isFavorite(_ landmark: Landmark) -> Bool {
250
+ favorites.contains(landmark)
251
+ }
252
+ }
253
+
254
+ struct LandmarkRow: View {
255
+ let landmark: Landmark
256
+ @Environment(ModelData.self) private var model
257
+
258
+ var body: some View {
259
+ HStack {
260
+ Text(landmark.name)
261
+ if model.isFavorite(landmark) {
262
+ Image(systemName: "heart.fill")
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ // GOOD - each item has its own observable view model
269
+ @Observable
270
+ class LandmarkViewModel {
271
+ var isFavorite: Bool = false
272
+ }
273
+
274
+ struct LandmarkRow: View {
275
+ let landmark: Landmark
276
+ let viewModel: LandmarkViewModel
277
+
278
+ var body: some View {
279
+ HStack {
280
+ Text(landmark.name)
281
+ if viewModel.isFavorite {
282
+ Image(systemName: "heart.fill")
283
+ }
284
+ }
285
+ }
286
+ }
287
+ ```
288
+
289
+ **Why**: With the bad pattern, toggling one favorite marks the entire array as changed, causing every `LandmarkRow` to re-run its body. With per-item view models, only the toggled item's body runs.
290
+
291
+ > Source: "Optimize SwiftUI performance with Instruments" (WWDC25, session 306)
292
+
293
+ ### 11. Off-Main-Thread Closures
294
+
295
+ **SwiftUI may call certain closures on a background thread for performance.** These closures must be `Sendable` and should avoid accessing `@MainActor`-isolated state directly. Instead, capture needed values in the closure's capture list.
296
+
297
+ Closures that may run off the main thread:
298
+ - `Shape.path(in:)`
299
+ - `visualEffect` closure
300
+ - `Layout` protocol methods
301
+ - `onGeometryChange` transform closure
302
+
303
+ ```swift
304
+ // BAD - accessing @MainActor state directly
305
+ .visualEffect { content, geometry in
306
+ content.blur(radius: self.pulse ? 5 : 0) // Compiler error: @MainActor isolated
307
+ }
308
+
309
+ // GOOD - capture the value
310
+ .visualEffect { [pulse] content, geometry in
311
+ content.blur(radius: pulse ? 5 : 0)
312
+ }
313
+ ```
314
+
315
+ > Source: "Explore concurrency in SwiftUI" (WWDC25, session 266)
316
+
317
+ ### 12. Common Performance Issues
318
+
319
+ **Be aware of common performance bottlenecks in SwiftUI:**
320
+
321
+ - View invalidation storms from broad state changes
322
+ - Unstable identity in lists causing excessive diffing
323
+ - Heavy work in `body` (formatting, sorting, image decoding)
324
+ - Layout thrash from deep stacks or preference chains
325
+
326
+ **When performance issues arise**, suggest the user profile with Instruments (SwiftUI template) to identify specific bottlenecks.
327
+
328
+ ## Anti-Patterns
329
+
330
+ ### 1. Creating Objects in Body
331
+
332
+ ```swift
333
+ // BAD - creates new formatter every body call
334
+ var body: some View {
335
+ let formatter = DateFormatter()
336
+ formatter.dateStyle = .long
337
+ return Text(formatter.string(from: date))
338
+ }
339
+
340
+ // GOOD - static or stored formatter
341
+ private static let dateFormatter: DateFormatter = {
342
+ let f = DateFormatter()
343
+ f.dateStyle = .long
344
+ return f
345
+ }()
346
+
347
+ var body: some View {
348
+ Text(Self.dateFormatter.string(from: date))
349
+ }
350
+ ```
351
+
352
+ ### 2. Heavy Computation in Body
353
+
354
+ **Keep view body simple and pure.** Avoid side effects, dispatching, or complex logic.
355
+
356
+ ```swift
357
+ // BAD - sorts array every body call
358
+ var body: some View {
359
+ List(items.sorted { $0.name < $1.name }) { item in Text(item.name) }
360
+ }
361
+
362
+ // GOOD - compute once, update via onChange or a computed property in the model
363
+ @State private var sortedItems: [Item] = []
364
+
365
+ var body: some View {
366
+ List(sortedItems) { item in Text(item.name) }
367
+ .onChange(of: items) { _, newItems in
368
+ sortedItems = newItems.sorted { $0.name < $1.name }
369
+ }
370
+ }
371
+ ```
372
+
373
+ Move sorting, filtering, and formatting into models or computed properties. The `body` should be a pure structural representation of state.
374
+
375
+ ### 3. Unnecessary State
376
+
377
+ ```swift
378
+ // BAD - derived state stored separately
379
+ @State private var items: [Item] = []
380
+ @State private var itemCount: Int = 0 // Unnecessary!
381
+
382
+ // GOOD - compute derived values
383
+ @State private var items: [Item] = []
384
+
385
+ var itemCount: Int { items.count } // Computed property
386
+ ```
387
+
388
+ ## Summary Checklist
389
+
390
+ - [ ] State updates check for value changes before assigning
391
+ - [ ] Hot paths minimize state updates
392
+ - [ ] Pass only needed values to views (avoid large config objects)
393
+ - [ ] Large lists use `LazyVStack`/`LazyHStack`
394
+ - [ ] No object creation in `body`
395
+ - [ ] Heavy computation moved out of `body`
396
+ - [ ] Body kept simple and pure (no side effects)
397
+ - [ ] Derived state computed, not stored
398
+ - [ ] Use `Self._logChanges()` or `Self._printChanges()` to debug unexpected updates
399
+ - [ ] Equatable conformance for expensive views (when appropriate)
400
+ - [ ] Consider POD view wrappers for advanced optimization
401
+ - [ ] Consider using granular @Observable dependencies for list items (smaller observable units per row when it measurably reduces updates)
402
+ - [ ] Frequently-changing values not stored in the environment
403
+ - [ ] Sendable closures (Shape, visualEffect, Layout) capture values instead of accessing @MainActor state