buildanything 1.7.0 → 1.8.0

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 (222) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +55 -0
  4. package/README.md +71 -61
  5. package/agents/ios-app-review-guardian.md +49 -0
  6. package/agents/ios-foundation-models-specialist.md +46 -0
  7. package/agents/ios-storekit-specialist.md +52 -0
  8. package/agents/ios-swift-architect.md +102 -0
  9. package/agents/ios-swift-search.md +130 -0
  10. package/agents/ios-swift-ui-design.md +104 -0
  11. package/commands/build.md +80 -176
  12. package/commands/fix.md +65 -0
  13. package/commands/setup.md +73 -0
  14. package/commands/ux-review.md +63 -0
  15. package/commands/verify.md +72 -0
  16. package/hooks/session-start +18 -1
  17. package/package.json +5 -2
  18. package/protocols/brainstorm.md +99 -0
  19. package/protocols/build-fix.md +52 -0
  20. package/protocols/cleanup.md +54 -0
  21. package/protocols/design.md +269 -0
  22. package/protocols/eval-harness.md +61 -0
  23. package/protocols/fake-data-detector.md +64 -0
  24. package/protocols/ios-context.md +235 -0
  25. package/protocols/ios-frameworks-map.md +323 -0
  26. package/protocols/ios-phase-branches.md +162 -0
  27. package/protocols/ios-preflight.md +27 -0
  28. package/protocols/metric-loop.md +93 -0
  29. package/protocols/planning.md +87 -0
  30. package/protocols/smoke-test.md +110 -0
  31. package/protocols/verify.md +67 -0
  32. package/protocols/web-phase-branches.md +201 -0
  33. package/skills/ios/_VENDORED.md +60 -0
  34. package/skills/ios/activitykit/LICENSE +131 -0
  35. package/skills/ios/activitykit/SKILL.md +505 -0
  36. package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
  37. package/skills/ios/app-intents/LICENSE +131 -0
  38. package/skills/ios/app-intents/SKILL.md +494 -0
  39. package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
  40. package/skills/ios/apple-on-device-ai/LICENSE +131 -0
  41. package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
  42. package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
  43. package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
  44. package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
  45. package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
  46. package/skills/ios/ios-26-platform/SKILL.md +53 -0
  47. package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
  48. package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
  49. package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
  50. package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
  51. package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
  52. package/skills/ios/ios-bootstrap/SKILL.md +98 -0
  53. package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
  54. package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
  55. package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
  56. package/skills/ios/ios-debugger-agent/LICENSE +21 -0
  57. package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
  58. package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
  59. package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
  60. package/skills/ios/ios-hig/SKILL.md +41 -0
  61. package/skills/ios/ios-hig/references/accessibility.md +81 -0
  62. package/skills/ios/ios-hig/references/content.md +142 -0
  63. package/skills/ios/ios-hig/references/feedback.md +123 -0
  64. package/skills/ios/ios-hig/references/interaction.md +199 -0
  65. package/skills/ios/ios-hig/references/performance-platform.md +129 -0
  66. package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
  67. package/skills/ios/ios-hig/references/visual-design.md +84 -0
  68. package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
  69. package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
  70. package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
  71. package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
  72. package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
  73. package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
  74. package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
  75. package/skills/ios/swift-accessibility/LICENSE +21 -0
  76. package/skills/ios/swift-accessibility/SKILL.md +371 -0
  77. package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
  78. package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
  79. package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
  80. package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
  81. package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
  82. package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
  83. package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
  84. package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
  85. package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
  86. package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
  87. package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
  88. package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
  89. package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
  90. package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
  91. package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
  92. package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
  93. package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
  94. package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
  95. package/skills/ios/swift-concurrency/LICENSE +21 -0
  96. package/skills/ios/swift-concurrency/SKILL.md +171 -0
  97. package/skills/ios/swift-concurrency/references/_index.md +50 -0
  98. package/skills/ios/swift-concurrency/references/actors.md +660 -0
  99. package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
  100. package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
  101. package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
  102. package/skills/ios/swift-concurrency/references/core-data.md +560 -0
  103. package/skills/ios/swift-concurrency/references/glossary.md +135 -0
  104. package/skills/ios/swift-concurrency/references/linting.md +155 -0
  105. package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
  106. package/skills/ios/swift-concurrency/references/migration.md +1104 -0
  107. package/skills/ios/swift-concurrency/references/performance.md +593 -0
  108. package/skills/ios/swift-concurrency/references/sendable.md +598 -0
  109. package/skills/ios/swift-concurrency/references/tasks.md +636 -0
  110. package/skills/ios/swift-concurrency/references/testing.md +592 -0
  111. package/skills/ios/swift-concurrency/references/threading.md +495 -0
  112. package/skills/ios/swift-security-expert/LICENSE +21 -0
  113. package/skills/ios/swift-security-expert/SKILL.md +470 -0
  114. package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
  115. package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
  116. package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
  117. package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
  118. package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
  119. package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
  120. package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
  121. package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
  122. package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
  123. package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
  124. package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
  125. package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
  126. package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
  127. package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
  128. package/skills/ios/swift-testing-expert/LICENSE +21 -0
  129. package/skills/ios/swift-testing-expert/SKILL.md +79 -0
  130. package/skills/ios/swift-testing-expert/references/_index.md +12 -0
  131. package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
  132. package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
  133. package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
  134. package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
  135. package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
  136. package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
  137. package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
  138. package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
  139. package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
  140. package/skills/ios/swiftdata-pro/LICENSE +21 -0
  141. package/skills/ios/swiftdata-pro/SKILL.md +102 -0
  142. package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
  143. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
  144. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
  145. package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
  146. package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
  147. package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
  148. package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
  149. package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
  150. package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
  151. package/skills/ios/swiftui-design-principles/LICENSE +21 -0
  152. package/skills/ios/swiftui-design-principles/README.md +41 -0
  153. package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
  154. package/skills/ios/swiftui-design-principles/metadata.json +10 -0
  155. package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
  156. package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
  157. package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
  158. package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  159. package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
  160. package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
  161. package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
  162. package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
  163. package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  164. package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  165. package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
  166. package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
  167. package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  168. package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  169. package/skills/ios/swiftui-pro/LICENSE +21 -0
  170. package/skills/ios/swiftui-pro/SKILL.md +108 -0
  171. package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
  172. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  173. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  174. package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
  175. package/skills/ios/swiftui-pro/references/api.md +39 -0
  176. package/skills/ios/swiftui-pro/references/data.md +43 -0
  177. package/skills/ios/swiftui-pro/references/design.md +31 -0
  178. package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
  179. package/skills/ios/swiftui-pro/references/navigation.md +14 -0
  180. package/skills/ios/swiftui-pro/references/performance.md +46 -0
  181. package/skills/ios/swiftui-pro/references/swift.md +56 -0
  182. package/skills/ios/swiftui-pro/references/views.md +35 -0
  183. package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
  184. package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
  185. package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
  186. package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
  187. package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
  188. package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
  189. package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
  190. package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
  191. package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
  192. package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
  193. package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
  194. package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
  195. package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  196. package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  197. package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
  198. package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  199. package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
  200. package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  201. package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
  202. package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
  203. package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
  204. package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
  205. package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
  206. package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
  207. package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  208. package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
  209. package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
  210. package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
  211. package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
  212. package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
  213. package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
  214. package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
  215. package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
  216. package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
  217. package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
  218. package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
  219. package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
  220. package/skills/ios/widgetkit/LICENSE +131 -0
  221. package/skills/ios/widgetkit/SKILL.md +502 -0
  222. package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
@@ -0,0 +1,393 @@
1
+ # Motor and Alternative Input
2
+
3
+ Covers accessibility for users who interact with devices through means other than direct touch: Switch Control, Full Keyboard Access, AssistiveTouch, and Guided Access.
4
+
5
+ ## Contents
6
+ - [Touch Target Sizing](#touch-target-sizing)
7
+ - [Switch Control](#switch-control)
8
+ - [Full Keyboard Access (iOS / iPadOS)](#full-keyboard-access-ios--ipados)
9
+ - [tvOS Focus Engine](#tvos-focus-engine)
10
+ - [AssistiveTouch](#assistivetouch)
11
+ - [Guided Access](#guided-access)
12
+ - [Common Patterns Checklist](#common-patterns-checklist)
13
+
14
+ ---
15
+
16
+ ## Touch Target Sizing
17
+
18
+ All interactive elements must have a touch target of at least **44×44 points**. Small targets are a Nutrition Label failure and a common accessibility audit finding.
19
+
20
+ ### SwiftUI
21
+
22
+ ```swift
23
+ // ✅ contentShape extends the hit area without changing visual size
24
+ Image(systemName: "heart")
25
+ .font(.system(size: 20))
26
+ .contentShape(Rectangle())
27
+ .frame(minWidth: 44, minHeight: 44)
28
+
29
+ // ✅ Alternatively, use padding to expand the tap area
30
+ Button { toggleFavorite() } label: {
31
+ Image(systemName: "heart").font(.system(size: 20))
32
+ }
33
+ .padding(12) // expands tap area to ~44pt
34
+
35
+ // ❌ Visual and tap area are both 20×20
36
+ Image(systemName: "heart")
37
+ .font(.system(size: 20))
38
+ .onTapGesture { toggleFavorite() }
39
+ ```
40
+
41
+ ### UIKit
42
+
43
+ ```swift
44
+ // Override pointInside to extend the hit area
45
+ class LargeHitButton: UIButton {
46
+ var hitAreaInsets = UIEdgeInsets(top: -12, left: -12, bottom: -12, right: -12)
47
+
48
+ override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
49
+ let hitArea = bounds.inset(by: hitAreaInsets)
50
+ return hitArea.contains(point)
51
+ }
52
+ }
53
+
54
+ // Or override accessibilityFrame to report a larger area
55
+ override var accessibilityFrame: CGRect {
56
+ let frame = convert(bounds, to: nil)
57
+ let minSize: CGFloat = 44
58
+ let dX = max(0, (minSize - frame.width) / 2)
59
+ let dY = max(0, (minSize - frame.height) / 2)
60
+ return frame.insetBy(dx: -dX, dy: -dY)
61
+ }
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Switch Control
67
+
68
+ Switch Control allows users to navigate with one or more adaptive switches (physical buttons, sip-and-puff, sound input). Items highlight sequentially; the user activates their switch to select the highlighted element.
69
+
70
+ ### How Navigation Works
71
+
72
+ 1. **Item scanning** — elements highlight one by one
73
+ 2. **Group scanning** — groups highlight first, then individual items within
74
+ 3. **Point scanning** — a crosshair moves across the screen
75
+
76
+ Developers primarily need to ensure:
77
+ - All interactive elements are reachable
78
+ - Operations don't time out
79
+ - Complex gestures have switch-accessible alternatives
80
+
81
+ ### Custom Actions for Gestures
82
+
83
+ Any swipe, long-press, or multi-touch gesture must have a custom action alternative.
84
+
85
+ ```swift
86
+ // SwiftUI
87
+ FeedCard(post: post)
88
+ .accessibilityAction(named: "Like") { like(post) }
89
+ .accessibilityAction(named: "Comment") { showComment(post) }
90
+ .accessibilityAction(named: "Share") { share(post) }
91
+ .accessibilityAction(named: "Save") { save(post) }
92
+
93
+ // UIKit
94
+ cell.accessibilityCustomActions = [
95
+ UIAccessibilityCustomAction(name: "Like") { _ in self.like(post); return true },
96
+ UIAccessibilityCustomAction(name: "Share") { _ in self.share(post); return true }
97
+ ]
98
+ ```
99
+
100
+ ### Grouping for Efficient Scanning
101
+
102
+ Use `shouldGroupAccessibilityChildren = true` (UIKit) or `.accessibilityElement(children: .contain)` (SwiftUI) to create a group. Users can skip the whole group with one switch tap if it's not relevant.
103
+
104
+ ```swift
105
+ // SwiftUI — group sidebar as a unit
106
+ SidebarView()
107
+ .accessibilityElement(children: .contain)
108
+ .accessibilityLabel("Sidebar")
109
+
110
+ // UIKit
111
+ sidebarView.shouldGroupAccessibilityChildren = true
112
+ sidebarView.accessibilityLabel = "Sidebar"
113
+ ```
114
+
115
+ ### Detecting Switch Control
116
+
117
+ Use only for UI optimization, never to branch core logic.
118
+
119
+ ```swift
120
+ if UIAccessibility.isSwitchControlRunning {
121
+ // Simplify animations, increase tap target feedback
122
+ }
123
+ ```
124
+
125
+ ### Time-Limited Interactions
126
+
127
+ Never require interactions to complete within a fixed time window. Switch Control users operate significantly slower than direct touch.
128
+
129
+ ```swift
130
+ // ❌ Auto-advances after 3 seconds — inaccessible
131
+ DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
132
+ self.advanceToNextStep()
133
+ }
134
+
135
+ // ✅ Require explicit user action
136
+ Button("Next Step") { advanceToNextStep() }
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Full Keyboard Access (iOS / iPadOS)
142
+
143
+ Full Keyboard Access (Settings → Accessibility → Keyboards → Full Keyboard Access) allows complete navigation using a hardware keyboard. Essential for iPad users and Mac Catalyst apps.
144
+
145
+ ### How It Works
146
+
147
+ - **Tab** — move focus forward
148
+ - **Shift+Tab** — move focus backward
149
+ - **Space / Return** — activate focused element
150
+ - **Escape** — dismiss modal / cancel
151
+ - **Arrow keys** — navigate within components (pickers, sliders)
152
+
153
+ ### All Elements Must Be Keyboard-Focusable
154
+
155
+ Native SwiftUI and UIKit controls are keyboard-accessible by default. Custom interactive views require opt-in.
156
+
157
+ ```swift
158
+ // SwiftUI — custom tappable view needs to be a Button or use .accessibilityAddTraits(.isButton)
159
+ // Non-Button views that use onTapGesture may not receive keyboard focus
160
+
161
+ // ✅ Button receives keyboard focus automatically
162
+ Button("Open Settings") { openSettings() }
163
+
164
+ // ⚠️ Custom view — test keyboard navigation explicitly
165
+ CustomTileView()
166
+ .accessibilityAddTraits(.isButton)
167
+ .onTapGesture { handleTap() }
168
+ // May not receive keyboard focus — prefer using Button
169
+ ```
170
+
171
+ ### Detecting Full Keyboard Access
172
+
173
+ ```swift
174
+ if UIAccessibility.isFullKeyboardAccessEnabled {
175
+ // Show keyboard shortcut hints in UI
176
+ }
177
+ ```
178
+
179
+ ### Modal Dismissal via Escape
180
+
181
+ Every modal, sheet, popover, and alert must be dismissible with the Escape key.
182
+
183
+ ```swift
184
+ // SwiftUI — sheets dismiss via Escape automatically when using .sheet()
185
+ .sheet(isPresented: $showSettings) {
186
+ SettingsView()
187
+ }
188
+
189
+ // UIKit custom modal — implement accessibilityPerformEscape
190
+ class CustomModalViewController: UIViewController {
191
+ override func accessibilityPerformEscape() -> Bool {
192
+ dismiss(animated: true)
193
+ return true
194
+ }
195
+ }
196
+ ```
197
+
198
+ ### Focus Guide — Bridge Focus Gaps
199
+
200
+ When keyboard focus can't naturally reach an area of the screen (e.g., a floating button overlaps other content), use `UIFocusGuide` to redirect focus.
201
+
202
+ ```swift
203
+ // UIKit
204
+ let focusGuide = UIFocusGuide()
205
+ view.addLayoutGuide(focusGuide)
206
+ focusGuide.preferredFocusEnvironments = [floatingButton]
207
+
208
+ // Constrain the guide to fill the gap area
209
+ NSLayoutConstraint.activate([
210
+ focusGuide.topAnchor.constraint(equalTo: gapArea.topAnchor),
211
+ focusGuide.leadingAnchor.constraint(equalTo: gapArea.leadingAnchor),
212
+ focusGuide.trailingAnchor.constraint(equalTo: gapArea.trailingAnchor),
213
+ focusGuide.bottomAnchor.constraint(equalTo: gapArea.bottomAnchor)
214
+ ])
215
+ ```
216
+
217
+ ### `accessibilityRespondsToUserInteraction(_:)` (SwiftUI, iOS 17+)
218
+
219
+ Marks a view as interactive for keyboard focus purposes.
220
+
221
+ ```swift
222
+ CustomInteractiveView()
223
+ .accessibilityRespondsToUserInteraction(true)
224
+ ```
225
+
226
+ ---
227
+
228
+ ## tvOS Focus Engine
229
+
230
+ On tvOS, the Siri Remote navigates entirely through the **Focus Engine**. There is no pointer; UI elements highlight as they receive focus.
231
+
232
+ ### Focus Basics
233
+
234
+ - Every focusable view must implement `canBecomeFocused` or use a native focusable control
235
+ - Focus moves between elements using the Siri Remote directional pad
236
+ - The Menu button = back / escape
237
+ - Long-press on Select = context menu
238
+
239
+ ### Making Custom Views Focusable
240
+
241
+ ```swift
242
+ // UIKit (tvOS)
243
+ class FocusableCardView: UIView {
244
+ override var canBecomeFocused: Bool { true }
245
+
246
+ override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
247
+ if context.nextFocusedView === self {
248
+ coordinator.addCoordinatedAnimations({
249
+ self.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
250
+ self.layer.shadowOpacity = 0.5
251
+ })
252
+ } else if context.previouslyFocusedView === self {
253
+ coordinator.addCoordinatedAnimations({
254
+ self.transform = .identity
255
+ self.layer.shadowOpacity = 0
256
+ })
257
+ }
258
+ }
259
+ }
260
+ ```
261
+
262
+ ### Setting Default Focus
263
+
264
+ ```swift
265
+ // UIKit — preferredFocusEnvironments is evaluated top-to-bottom
266
+ override var preferredFocusEnvironments: [UIFocusEnvironment] {
267
+ return [primaryButton]
268
+ }
269
+
270
+ // Deprecated — use preferredFocusEnvironments (shown above) instead
271
+ override weak var preferredFocusedView: UIView? { primaryButton }
272
+ ```
273
+
274
+ ### UIFocusGuide — Redirect Focus
275
+
276
+ ```swift
277
+ let guide = UIFocusGuide()
278
+ view.addLayoutGuide(guide)
279
+ guide.preferredFocusEnvironments = [targetButton]
280
+
281
+ // Guide occupies the empty space between two buttons
282
+ NSLayoutConstraint.activate([
283
+ guide.leadingAnchor.constraint(equalTo: leftButton.trailingAnchor),
284
+ guide.trailingAnchor.constraint(equalTo: rightButton.leadingAnchor),
285
+ guide.topAnchor.constraint(equalTo: leftButton.topAnchor),
286
+ guide.bottomAnchor.constraint(equalTo: leftButton.bottomAnchor)
287
+ ])
288
+ ```
289
+
290
+ ### Debugging Focus
291
+
292
+ In the iOS Simulator with tvOS target: Debug → View → Show Focus for Focus Engine Debug.
293
+
294
+ ---
295
+
296
+ ## AssistiveTouch
297
+
298
+ AssistiveTouch displays a floating virtual button that provides access to gestures, hardware buttons, and custom sequences. Most AssistiveTouch support is automatic if VoiceOver and basic accessibility are implemented.
299
+
300
+ ### Detecting AssistiveTouch
301
+
302
+ ```swift
303
+ if UIAccessibility.isAssistiveTouchRunning {
304
+ // Optional: simplify complex gestures, show alternative controls
305
+ }
306
+
307
+ // Observe changes
308
+ NotificationCenter.default.addObserver(
309
+ forName: UIAccessibility.assistiveTouchStatusDidChangeNotification,
310
+ object: nil, queue: .main
311
+ ) { _ in
312
+ // Update UI
313
+ }
314
+ ```
315
+
316
+ ### AssistiveTouch + Custom Gestures
317
+
318
+ Custom multi-touch gestures are inaccessible to AssistiveTouch. Always provide single-tap or button alternatives.
319
+
320
+ ---
321
+
322
+ ## Guided Access
323
+
324
+ Guided Access locks the device to a single app with optional feature restrictions. Used in kiosks, educational apps, and focus-mode scenarios.
325
+
326
+ ### Checking Guided Access State
327
+
328
+ ```swift
329
+ if UIAccessibility.isGuidedAccessEnabled {
330
+ // Lock navigation, hide sensitive controls
331
+ }
332
+
333
+ // Observe changes
334
+ NotificationCenter.default.addObserver(
335
+ forName: UIAccessibility.guidedAccessStatusDidChangeNotification,
336
+ object: nil, queue: .main
337
+ ) { _ in
338
+ updateForGuidedAccess()
339
+ }
340
+ ```
341
+
342
+ ### GuidedAccessRestrictions — Per-Feature Restrictions
343
+
344
+ Implement `UIGuidedAccessRestrictionDelegate` to offer fine-grained restrictions that educators or caregivers can toggle.
345
+
346
+ ```swift
347
+ class AppDelegate: UIResponder, UIApplicationDelegate, UIGuidedAccessRestrictionDelegate {
348
+
349
+ var guidedAccessRestrictionIdentifiers: [String] {
350
+ ["com.myapp.restriction.settings",
351
+ "com.myapp.restriction.purchases"]
352
+ }
353
+
354
+ func textForGuidedAccessRestriction(withIdentifier restrictionIdentifier: String) -> String? {
355
+ switch restrictionIdentifier {
356
+ case "com.myapp.restriction.settings": return "Settings"
357
+ case "com.myapp.restriction.purchases": return "In-App Purchases"
358
+ default: return nil
359
+ }
360
+ }
361
+
362
+ func guidedAccessRestriction(withIdentifier restrictionIdentifier: String,
363
+ didChange newRestrictionState: UIAccessibility.GuidedAccessRestrictionState) {
364
+ switch restrictionIdentifier {
365
+ case "com.myapp.restriction.settings":
366
+ settingsButton.isHidden = (newRestrictionState == .deny)
367
+ default: break
368
+ }
369
+ }
370
+ }
371
+ ```
372
+
373
+ ### Programmatic Guided Access Control
374
+
375
+ ```swift
376
+ // Enter/exit Single App Mode programmatically (for kiosk apps)
377
+ // Note: requires a supervised device or MDM enrollment
378
+ UIAccessibility.requestGuidedAccessSession(enabled: true) { success in
379
+ if success { print("Guided Access session started") }
380
+ }
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Common Patterns Checklist
386
+
387
+ - [ ] All interactive elements ≥ 44×44pt touch target
388
+ - [ ] Swipe-only gestures have `accessibilityCustomAction` alternatives
389
+ - [ ] No interactions time out without user control
390
+ - [ ] Every modal dismissible with Escape key
391
+ - [ ] Custom views use `Button` or have `.accessibilityTraits(.button)` for keyboard reachability
392
+ - [ ] tvOS: custom views override `canBecomeFocused` and animate focus changes
393
+ - [ ] Guided Access restrictions defined if app has lockable features