agy-superpowers 5.0.8 → 5.0.9

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 (204) hide show
  1. package/package.json +1 -1
  2. package/template/agent/rules/superpowers.md +54 -0
  3. package/template/agent/skills/frontend-developer/SKILL.md +39 -0
  4. package/template/agent/skills/frontend-developer/references/react-nextjs.md +343 -0
  5. package/template/agent/skills/frontend-developer/references/react-rules/_sections.md +46 -0
  6. package/template/agent/skills/frontend-developer/references/react-rules/_template.md +28 -0
  7. package/template/agent/skills/frontend-developer/references/react-rules/advanced-event-handler-refs.md +55 -0
  8. package/template/agent/skills/frontend-developer/references/react-rules/advanced-init-once.md +42 -0
  9. package/template/agent/skills/frontend-developer/references/react-rules/advanced-use-latest.md +39 -0
  10. package/template/agent/skills/frontend-developer/references/react-rules/async-api-routes.md +38 -0
  11. package/template/agent/skills/frontend-developer/references/react-rules/async-defer-await.md +80 -0
  12. package/template/agent/skills/frontend-developer/references/react-rules/async-dependencies.md +51 -0
  13. package/template/agent/skills/frontend-developer/references/react-rules/async-parallel.md +28 -0
  14. package/template/agent/skills/frontend-developer/references/react-rules/async-suspense-boundaries.md +99 -0
  15. package/template/agent/skills/frontend-developer/references/react-rules/bundle-barrel-imports.md +59 -0
  16. package/template/agent/skills/frontend-developer/references/react-rules/bundle-conditional.md +31 -0
  17. package/template/agent/skills/frontend-developer/references/react-rules/bundle-defer-third-party.md +49 -0
  18. package/template/agent/skills/frontend-developer/references/react-rules/bundle-dynamic-imports.md +35 -0
  19. package/template/agent/skills/frontend-developer/references/react-rules/bundle-preload.md +50 -0
  20. package/template/agent/skills/frontend-developer/references/react-rules/client-event-listeners.md +74 -0
  21. package/template/agent/skills/frontend-developer/references/react-rules/client-localstorage-schema.md +71 -0
  22. package/template/agent/skills/frontend-developer/references/react-rules/client-passive-event-listeners.md +48 -0
  23. package/template/agent/skills/frontend-developer/references/react-rules/client-swr-dedup.md +56 -0
  24. package/template/agent/skills/frontend-developer/references/react-rules/js-batch-dom-css.md +107 -0
  25. package/template/agent/skills/frontend-developer/references/react-rules/js-cache-function-results.md +80 -0
  26. package/template/agent/skills/frontend-developer/references/react-rules/js-cache-property-access.md +28 -0
  27. package/template/agent/skills/frontend-developer/references/react-rules/js-cache-storage.md +70 -0
  28. package/template/agent/skills/frontend-developer/references/react-rules/js-combine-iterations.md +32 -0
  29. package/template/agent/skills/frontend-developer/references/react-rules/js-early-exit.md +50 -0
  30. package/template/agent/skills/frontend-developer/references/react-rules/js-flatmap-filter.md +60 -0
  31. package/template/agent/skills/frontend-developer/references/react-rules/js-hoist-regexp.md +45 -0
  32. package/template/agent/skills/frontend-developer/references/react-rules/js-index-maps.md +37 -0
  33. package/template/agent/skills/frontend-developer/references/react-rules/js-length-check-first.md +49 -0
  34. package/template/agent/skills/frontend-developer/references/react-rules/js-min-max-loop.md +82 -0
  35. package/template/agent/skills/frontend-developer/references/react-rules/js-set-map-lookups.md +24 -0
  36. package/template/agent/skills/frontend-developer/references/react-rules/js-tosorted-immutable.md +57 -0
  37. package/template/agent/skills/frontend-developer/references/react-rules/rendering-activity.md +26 -0
  38. package/template/agent/skills/frontend-developer/references/react-rules/rendering-animate-svg-wrapper.md +47 -0
  39. package/template/agent/skills/frontend-developer/references/react-rules/rendering-conditional-render.md +40 -0
  40. package/template/agent/skills/frontend-developer/references/react-rules/rendering-content-visibility.md +38 -0
  41. package/template/agent/skills/frontend-developer/references/react-rules/rendering-hoist-jsx.md +46 -0
  42. package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-no-flicker.md +82 -0
  43. package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-suppress-warning.md +30 -0
  44. package/template/agent/skills/frontend-developer/references/react-rules/rendering-resource-hints.md +85 -0
  45. package/template/agent/skills/frontend-developer/references/react-rules/rendering-script-defer-async.md +68 -0
  46. package/template/agent/skills/frontend-developer/references/react-rules/rendering-svg-precision.md +28 -0
  47. package/template/agent/skills/frontend-developer/references/react-rules/rendering-usetransition-loading.md +75 -0
  48. package/template/agent/skills/frontend-developer/references/react-rules/rerender-defer-reads.md +39 -0
  49. package/template/agent/skills/frontend-developer/references/react-rules/rerender-dependencies.md +45 -0
  50. package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state-no-effect.md +40 -0
  51. package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state.md +29 -0
  52. package/template/agent/skills/frontend-developer/references/react-rules/rerender-functional-setstate.md +74 -0
  53. package/template/agent/skills/frontend-developer/references/react-rules/rerender-lazy-state-init.md +58 -0
  54. package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo-with-default-value.md +38 -0
  55. package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo.md +44 -0
  56. package/template/agent/skills/frontend-developer/references/react-rules/rerender-move-effect-to-event.md +45 -0
  57. package/template/agent/skills/frontend-developer/references/react-rules/rerender-no-inline-components.md +82 -0
  58. package/template/agent/skills/frontend-developer/references/react-rules/rerender-simple-expression-in-memo.md +35 -0
  59. package/template/agent/skills/frontend-developer/references/react-rules/rerender-split-combined-hooks.md +64 -0
  60. package/template/agent/skills/frontend-developer/references/react-rules/rerender-transitions.md +40 -0
  61. package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-deferred-value.md +59 -0
  62. package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-ref-transient-values.md +73 -0
  63. package/template/agent/skills/frontend-developer/references/react-rules/server-after-nonblocking.md +73 -0
  64. package/template/agent/skills/frontend-developer/references/react-rules/server-auth-actions.md +96 -0
  65. package/template/agent/skills/frontend-developer/references/react-rules/server-cache-lru.md +41 -0
  66. package/template/agent/skills/frontend-developer/references/react-rules/server-cache-react.md +76 -0
  67. package/template/agent/skills/frontend-developer/references/react-rules/server-dedup-props.md +65 -0
  68. package/template/agent/skills/frontend-developer/references/react-rules/server-hoist-static-io.md +142 -0
  69. package/template/agent/skills/frontend-developer/references/react-rules/server-parallel-fetching.md +83 -0
  70. package/template/agent/skills/frontend-developer/references/react-rules/server-serialization.md +38 -0
  71. package/template/agent/skills/frontend-developer/references/svelte-sveltekit.md +220 -0
  72. package/template/agent/skills/frontend-developer/references/vanilla.md +275 -0
  73. package/template/agent/skills/frontend-developer/references/vue-nuxt.md +289 -0
  74. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/_index.md +154 -0
  75. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-class-based-technique.md +254 -0
  76. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-state-driven-technique.md +291 -0
  77. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-async.md +97 -0
  78. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-data-flow.md +307 -0
  79. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-fallthrough-attrs.md +174 -0
  80. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-keep-alive.md +137 -0
  81. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-slots.md +216 -0
  82. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-suspense.md +228 -0
  83. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-teleport.md +108 -0
  84. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition-group.md +128 -0
  85. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition.md +125 -0
  86. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/composables.md +290 -0
  87. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/directives.md +162 -0
  88. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-avoid-component-abstraction-in-lists.md +159 -0
  89. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-v-once-v-memo-directives.md +182 -0
  90. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-virtualize-large-lists.md +187 -0
  91. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/plugins.md +166 -0
  92. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/reactivity.md +344 -0
  93. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/render-functions.md +201 -0
  94. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/sfc.md +310 -0
  95. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/state-management.md +135 -0
  96. package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/updated-hook-performance.md +187 -0
  97. package/template/agent/skills/frontend-developer/references/vue-rules/router/_index.md +23 -0
  98. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforeenter-no-param-trigger.md +167 -0
  99. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforerouteenter-no-this.md +176 -0
  100. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-guard-async-await-pattern.md +227 -0
  101. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-infinite-loop.md +187 -0
  102. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-next-deprecated.md +150 -0
  103. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-param-change-no-lifecycle.md +181 -0
  104. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-simple-routing-cleanup.md +209 -0
  105. package/template/agent/skills/frontend-developer/references/vue-rules/router/router-use-vue-router-for-production.md +183 -0
  106. package/template/agent/skills/frontend-developer/references/vue-rules/testing/_index.md +29 -0
  107. package/template/agent/skills/frontend-developer/references/vue-rules/testing/async-component-testing.md +163 -0
  108. package/template/agent/skills/frontend-developer/references/vue-rules/testing/teleport-testing-complexity.md +158 -0
  109. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-async-await-flushpromises.md +175 -0
  110. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-browser-vs-node-runners.md +208 -0
  111. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-component-blackbox-approach.md +144 -0
  112. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-composables-helper-wrapper.md +238 -0
  113. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-e2e-playwright-recommended.md +242 -0
  114. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-no-snapshot-only.md +197 -0
  115. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-pinia-store-setup.md +228 -0
  116. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-suspense-async-components.md +229 -0
  117. package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-vitest-recommended-for-vue.md +204 -0
  118. package/template/agent/skills/mobile-developer/SKILL.md +52 -0
  119. package/template/agent/skills/mobile-developer/references/android-native.md +396 -0
  120. package/template/agent/skills/mobile-developer/references/android-rules/android-accessibility.md +36 -0
  121. package/template/agent/skills/mobile-developer/references/android-rules/android-architecture.md +52 -0
  122. package/template/agent/skills/mobile-developer/references/android-rules/android-coroutines.md +139 -0
  123. package/template/agent/skills/mobile-developer/references/android-rules/android-data-layer.md +51 -0
  124. package/template/agent/skills/mobile-developer/references/android-rules/android-emulator-skill.md +108 -0
  125. package/template/agent/skills/mobile-developer/references/android-rules/android-gradle-logic.md +126 -0
  126. package/template/agent/skills/mobile-developer/references/android-rules/android-retrofit.md +142 -0
  127. package/template/agent/skills/mobile-developer/references/android-rules/android-testing.md +102 -0
  128. package/template/agent/skills/mobile-developer/references/android-rules/android-viewmodel.md +43 -0
  129. package/template/agent/skills/mobile-developer/references/android-rules/coil-compose.md +74 -0
  130. package/template/agent/skills/mobile-developer/references/android-rules/compose-navigation.md +422 -0
  131. package/template/agent/skills/mobile-developer/references/android-rules/compose-performance-audit.md +199 -0
  132. package/template/agent/skills/mobile-developer/references/android-rules/compose-ui.md +49 -0
  133. package/template/agent/skills/mobile-developer/references/android-rules/gradle-build-performance.md +346 -0
  134. package/template/agent/skills/mobile-developer/references/android-rules/kotlin-concurrency-expert.md +169 -0
  135. package/template/agent/skills/mobile-developer/references/android-rules/rxjava-to-coroutines-migration.md +101 -0
  136. package/template/agent/skills/mobile-developer/references/android-rules/xml-to-compose-migration.md +338 -0
  137. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-best-practices.md +52 -0
  138. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-checks-migration.md +134 -0
  139. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-cli-app-best-practices.md +123 -0
  140. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-doc-validation.md +45 -0
  141. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-matcher-best-practices.md +106 -0
  142. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-modern-features.md +241 -0
  143. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-package-maintenance.md +75 -0
  144. package/template/agent/skills/mobile-developer/references/flutter-rules/dart-test-fundamentals.md +124 -0
  145. package/template/agent/skills/mobile-developer/references/flutter.md +291 -0
  146. package/template/agent/skills/mobile-developer/references/ios-native.md +358 -0
  147. package/template/agent/skills/mobile-developer/references/ios-rules/accessibility-patterns.md +215 -0
  148. package/template/agent/skills/mobile-developer/references/ios-rules/animation-advanced.md +403 -0
  149. package/template/agent/skills/mobile-developer/references/ios-rules/animation-basics.md +284 -0
  150. package/template/agent/skills/mobile-developer/references/ios-rules/animation-transitions.md +326 -0
  151. package/template/agent/skills/mobile-developer/references/ios-rules/charts-accessibility.md +135 -0
  152. package/template/agent/skills/mobile-developer/references/ios-rules/charts.md +602 -0
  153. package/template/agent/skills/mobile-developer/references/ios-rules/image-optimization.md +203 -0
  154. package/template/agent/skills/mobile-developer/references/ios-rules/latest-apis.md +464 -0
  155. package/template/agent/skills/mobile-developer/references/ios-rules/layout-best-practices.md +266 -0
  156. package/template/agent/skills/mobile-developer/references/ios-rules/liquid-glass.md +416 -0
  157. package/template/agent/skills/mobile-developer/references/ios-rules/list-patterns.md +394 -0
  158. package/template/agent/skills/mobile-developer/references/ios-rules/macos-scenes.md +318 -0
  159. package/template/agent/skills/mobile-developer/references/ios-rules/macos-views.md +357 -0
  160. package/template/agent/skills/mobile-developer/references/ios-rules/macos-window-styling.md +303 -0
  161. package/template/agent/skills/mobile-developer/references/ios-rules/performance-patterns.md +403 -0
  162. package/template/agent/skills/mobile-developer/references/ios-rules/scroll-patterns.md +293 -0
  163. package/template/agent/skills/mobile-developer/references/ios-rules/sheet-navigation-patterns.md +363 -0
  164. package/template/agent/skills/mobile-developer/references/ios-rules/state-management.md +417 -0
  165. package/template/agent/skills/mobile-developer/references/ios-rules/view-structure.md +389 -0
  166. package/template/agent/skills/mobile-developer/references/react-native-rules/_sections.md +86 -0
  167. package/template/agent/skills/mobile-developer/references/react-native-rules/_template.md +28 -0
  168. package/template/agent/skills/mobile-developer/references/react-native-rules/animation-derived-value.md +53 -0
  169. package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gesture-detector-press.md +95 -0
  170. package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gpu-properties.md +65 -0
  171. package/template/agent/skills/mobile-developer/references/react-native-rules/design-system-compound-components.md +66 -0
  172. package/template/agent/skills/mobile-developer/references/react-native-rules/fonts-config-plugin.md +71 -0
  173. package/template/agent/skills/mobile-developer/references/react-native-rules/imports-design-system-folder.md +68 -0
  174. package/template/agent/skills/mobile-developer/references/react-native-rules/js-hoist-intl.md +61 -0
  175. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-callbacks.md +44 -0
  176. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-function-references.md +132 -0
  177. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-images.md +53 -0
  178. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-inline-objects.md +97 -0
  179. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-expensive.md +94 -0
  180. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-memo.md +82 -0
  181. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-types.md +104 -0
  182. package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-virtualize.md +67 -0
  183. package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-native-deps-in-app.md +46 -0
  184. package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-single-dependency-versions.md +63 -0
  185. package/template/agent/skills/mobile-developer/references/react-native-rules/navigation-native-navigators.md +188 -0
  186. package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-destructure-functions.md +50 -0
  187. package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-reanimated-shared-values.md +48 -0
  188. package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-dispatcher.md +91 -0
  189. package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-fallback.md +56 -0
  190. package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-minimize.md +65 -0
  191. package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-no-falsy-and.md +74 -0
  192. package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-text-in-text-component.md +36 -0
  193. package/template/agent/skills/mobile-developer/references/react-native-rules/scroll-position-no-state.md +82 -0
  194. package/template/agent/skills/mobile-developer/references/react-native-rules/state-ground-truth.md +80 -0
  195. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-expo-image.md +66 -0
  196. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-image-gallery.md +104 -0
  197. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-measure-views.md +78 -0
  198. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-menus.md +174 -0
  199. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-native-modals.md +77 -0
  200. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-pressable.md +61 -0
  201. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-safe-area-scroll.md +65 -0
  202. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-scrollview-content-inset.md +45 -0
  203. package/template/agent/skills/mobile-developer/references/react-native-rules/ui-styling.md +87 -0
  204. package/template/agent/skills/mobile-developer/references/react-native.md +345 -0
@@ -0,0 +1,215 @@
1
+ # SwiftUI Accessibility Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [Core Principle](#core-principle)
6
+ - [Dynamic Type and @ScaledMetric](#dynamic-type-and-scaledmetric)
7
+ - [Accessibility Traits](#accessibility-traits)
8
+ - [Decorative Images](#decorative-images)
9
+ - [Element Grouping](#element-grouping)
10
+ - [Custom Controls](#custom-controls)
11
+ - [Summary Checklist](#summary-checklist)
12
+
13
+ ## Core Principle
14
+
15
+ Prefer `Button` over `onTapGesture` for tappable elements. `Button` provides VoiceOver support, focus handling, and proper traits for free.
16
+
17
+ ## Dynamic Type and @ScaledMetric
18
+
19
+ System text styles scale with Dynamic Type automatically. Prefer built-in styles like `.largeTitle`, `.title`, `.title2`, `.title3`, `.headline`, `.subheadline`, `.body`, `.callout`, `.footnote`, `.caption`, and `.caption2` when they fit your UI:
20
+
21
+ ```swift
22
+ VStack(alignment: .leading) {
23
+ Text("Inbox")
24
+ .font(.title2)
25
+ Text("3 unread messages")
26
+ .font(.body)
27
+ Text("Updated just now")
28
+ .font(.caption)
29
+ }
30
+ ```
31
+
32
+ For custom fonts, use a Dynamic Type-aware font initializer so the text still follows the user's preferred content size:
33
+
34
+ ```swift
35
+ VStack(alignment: .leading) {
36
+ Text("Article")
37
+ .font(.custom("SourceSerif4-Semibold", size: 28, relativeTo: .title2))
38
+ Text("Body copy")
39
+ .font(.custom("SourceSerif4-Regular", size: 17))
40
+ }
41
+ ```
42
+
43
+ `Font.custom(_:size:relativeTo:)` lets you match a specific text style. `Font.custom(_:size:)` scales relative to the body style. Avoid fixed-size custom fonts for primary content that should respond to Dynamic Type.
44
+
45
+ For non-text numeric values like padding, spacing, and image sizes, use `@ScaledMetric`:
46
+
47
+ ```swift
48
+ struct ProfileHeader: View {
49
+ @ScaledMetric private var avatarSize = 60.0
50
+ @ScaledMetric private var spacing = 12.0
51
+
52
+ var body: some View {
53
+ HStack(spacing: spacing) {
54
+ Image("avatar")
55
+ .resizable()
56
+ .frame(width: avatarSize, height: avatarSize)
57
+ Text("Username")
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ Specify a `relativeTo` text style when the value should track a specific Dynamic Type style, including for images or icons that should stay proportional to nearby text:
64
+
65
+ ```swift
66
+ struct StatusRow: View {
67
+ @ScaledMetric(relativeTo: .body) private var iconSize = 18.0
68
+
69
+ var body: some View {
70
+ HStack(spacing: 8) {
71
+ Image(systemName: "checkmark.circle.fill")
72
+ .font(.system(size: iconSize))
73
+ Text("Synced")
74
+ .font(.custom("AvenirNext-Regular", size: 17, relativeTo: .body))
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ ## Accessibility Traits
81
+
82
+ Use `accessibilityAddTraits` and `accessibilityRemoveTraits` for state-driven traits:
83
+
84
+ ```swift
85
+ Text(item.title)
86
+ .accessibilityAddTraits(item.isSelected ? [.isSelected, .isButton] : .isButton)
87
+ ```
88
+
89
+ Use `.disabled(true)` to make VoiceOver announce "Dimmed" for non-interactive elements.
90
+
91
+ ## Decorative Images
92
+
93
+ Use `Image(decorative:bundle:)` when an asset image is purely visual and should not appear in the accessibility tree.
94
+
95
+ ```swift
96
+ Image(decorative: "confetti")
97
+ ```
98
+
99
+ This is appropriate for backgrounds, flourishes, and icons that do not add meaning beyond nearby text.
100
+
101
+ If the image conveys information, keep it accessible and provide a clear label:
102
+
103
+ ```swift
104
+ Image("receipt")
105
+ .accessibilityLabel("Receipt")
106
+ ```
107
+
108
+ For non-asset images, such as SF Symbols, hide decorative content with `accessibilityHidden(true)` instead:
109
+
110
+ ```swift
111
+ Image(systemName: "sparkles")
112
+ .accessibilityHidden(true)
113
+ ```
114
+
115
+ ## Element Grouping
116
+
117
+ ### .combine -- Auto-join child labels
118
+
119
+ ```swift
120
+ HStack {
121
+ Image(systemName: "star.fill")
122
+ Text("Favorites")
123
+ Text("(\(count))")
124
+ }
125
+ .accessibilityElement(children: .combine)
126
+ ```
127
+
128
+ VoiceOver reads all child labels as one element, separated by commas.
129
+
130
+ ### .ignore -- Manual label for container
131
+
132
+ ```swift
133
+ HStack {
134
+ Text(item.name)
135
+ Spacer()
136
+ Text(item.price)
137
+ }
138
+ .accessibilityElement(children: .ignore)
139
+ .accessibilityLabel("\(item.name), \(item.price)")
140
+ ```
141
+
142
+ ### .contain -- Semantic grouping
143
+
144
+ ```swift
145
+ HStack {
146
+ ForEach(tabs) { tab in
147
+ TabButton(tab: tab)
148
+ }
149
+ }
150
+ .accessibilityElement(children: .contain)
151
+ .accessibilityLabel("Tab bar")
152
+ ```
153
+
154
+ VoiceOver announces the container name when focus enters/exits.
155
+
156
+ ## Custom Controls
157
+
158
+ ### Adjustable controls (increment/decrement)
159
+
160
+ ```swift
161
+ PageControl(selectedIndex: $selectedIndex, pageCount: pageCount)
162
+ .accessibilityElement()
163
+ .accessibilityValue("Page \(selectedIndex + 1) of \(pageCount)")
164
+ .accessibilityAdjustableAction { direction in
165
+ switch direction {
166
+ case .increment:
167
+ guard selectedIndex < pageCount - 1 else { break }
168
+ selectedIndex += 1
169
+ case .decrement:
170
+ guard selectedIndex > 0 else { break }
171
+ selectedIndex -= 1
172
+ @unknown default:
173
+ break
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### Representing custom views as native controls
179
+
180
+ When a custom view should behave like a native control for accessibility:
181
+
182
+ ```swift
183
+ HStack {
184
+ Text(label)
185
+ Toggle("", isOn: $isOn)
186
+ }
187
+ .accessibilityRepresentation {
188
+ Toggle(label, isOn: $isOn)
189
+ }
190
+ ```
191
+
192
+ ### Label-content pairing
193
+
194
+ ```swift
195
+ @Namespace private var ns
196
+
197
+ HStack {
198
+ Text("Volume")
199
+ .accessibilityLabeledPair(role: .label, id: "volume", in: ns)
200
+ Slider(value: $volume)
201
+ .accessibilityLabeledPair(role: .content, id: "volume", in: ns)
202
+ }
203
+ ```
204
+
205
+ ## Summary Checklist
206
+
207
+ - [ ] Use `Button` instead of `onTapGesture` for tappable elements
208
+ - [ ] Use built-in text styles or Dynamic Type-aware custom fonts for text
209
+ - [ ] Use `@ScaledMetric` for custom values that should scale with Dynamic Type
210
+ - [ ] Mark purely decorative images as decorative or hidden from accessibility
211
+ - [ ] Group related elements with `accessibilityElement(children:)`
212
+ - [ ] Provide `accessibilityLabel` when default labels are unclear
213
+ - [ ] Use `accessibilityRepresentation` for custom controls
214
+ - [ ] Use `accessibilityAdjustableAction` for increment/decrement controls
215
+ - [ ] Ensure navigation flow is logical when using VoiceOver grouping
@@ -0,0 +1,403 @@
1
+ # SwiftUI Advanced Animations
2
+
3
+ Transactions, phase animations (iOS 17+), keyframe animations (iOS 17+), completion handlers (iOS 17+), and `@Animatable` macro (iOS 26+).
4
+
5
+ ## Table of Contents
6
+ - [Transactions](#transactions)
7
+ - [Phase Animations (iOS 17+)](#phase-animations-ios-17)
8
+ - [Keyframe Animations (iOS 17+)](#keyframe-animations-ios-17)
9
+ - [Animation Completion Handlers (iOS 17+)](#animation-completion-handlers-ios-17)
10
+ - [@Animatable Macro (iOS 26+)](#animatable-macro-ios-26)
11
+
12
+ ---
13
+
14
+ ## Transactions
15
+
16
+ The underlying mechanism for all animations in SwiftUI.
17
+
18
+ ### Basic Usage
19
+
20
+ ```swift
21
+ // withAnimation is shorthand for withTransaction
22
+ withAnimation(.default) { flag.toggle() }
23
+
24
+ // Equivalent explicit transaction
25
+ var transaction = Transaction(animation: .default)
26
+ withTransaction(transaction) { flag.toggle() }
27
+ ```
28
+
29
+ ### The .transaction Modifier
30
+
31
+ ```swift
32
+ Rectangle()
33
+ .frame(width: flag ? 100 : 50, height: 50)
34
+ .transaction { t in
35
+ t.animation = .default
36
+ }
37
+ ```
38
+
39
+ **Note:** This behaves like the deprecated `.animation(_:)` without value parameter - it animates on every state change.
40
+
41
+ ### Animation Precedence
42
+
43
+ **Implicit animations override explicit animations** (later in view tree wins).
44
+
45
+ ```swift
46
+ Button("Tap") {
47
+ withAnimation(.linear) { flag.toggle() }
48
+ }
49
+ .animation(.bouncy, value: flag) // .bouncy wins!
50
+ ```
51
+
52
+ ### Disabling Animations
53
+
54
+ ```swift
55
+ // Prevent implicit animations from overriding
56
+ .transaction { t in
57
+ t.disablesAnimations = true
58
+ }
59
+
60
+ // Remove animation entirely
61
+ .transaction { $0.animation = nil }
62
+ ```
63
+
64
+ ### Custom Transaction Keys (iOS 17+)
65
+
66
+ Pass metadata through transactions.
67
+
68
+ ```swift
69
+ struct ChangeSourceKey: TransactionKey {
70
+ static let defaultValue: String = "unknown"
71
+ }
72
+
73
+ extension Transaction {
74
+ var changeSource: String {
75
+ get { self[ChangeSourceKey.self] }
76
+ set { self[ChangeSourceKey.self] = newValue }
77
+ }
78
+ }
79
+
80
+ // Set source
81
+ var transaction = Transaction(animation: .default)
82
+ transaction.changeSource = "server"
83
+ withTransaction(transaction) { flag.toggle() }
84
+
85
+ // Read in view tree
86
+ .transaction { t in
87
+ if t.changeSource == "server" {
88
+ t.animation = .smooth
89
+ } else {
90
+ t.animation = .bouncy
91
+ }
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Phase Animations (iOS 17+)
98
+
99
+ Cycle through discrete phases automatically. Each phase change is a separate animation.
100
+
101
+ ### Basic Usage
102
+
103
+ ```swift
104
+ // GOOD - triggered phase animation
105
+ Button("Shake") { trigger += 1 }
106
+ .phaseAnimator(
107
+ [0.0, -10.0, 10.0, -5.0, 5.0, 0.0],
108
+ trigger: trigger
109
+ ) { content, offset in
110
+ content.offset(x: offset)
111
+ }
112
+
113
+ // Infinite loop (no trigger)
114
+ Circle()
115
+ .phaseAnimator([1.0, 1.2, 1.0]) { content, scale in
116
+ content.scaleEffect(scale)
117
+ }
118
+ ```
119
+
120
+ ### Enum Phases (Recommended for Clarity)
121
+
122
+ ```swift
123
+ // GOOD - enum phases are self-documenting
124
+ enum BouncePhase: CaseIterable {
125
+ case initial, up, down, settle
126
+
127
+ var scale: CGFloat {
128
+ switch self {
129
+ case .initial: 1.0
130
+ case .up: 1.2
131
+ case .down: 0.9
132
+ case .settle: 1.0
133
+ }
134
+ }
135
+ }
136
+
137
+ Circle()
138
+ .phaseAnimator(BouncePhase.allCases, trigger: trigger) { content, phase in
139
+ content.scaleEffect(phase.scale)
140
+ }
141
+ ```
142
+
143
+ ### Custom Timing Per Phase
144
+
145
+ ```swift
146
+ .phaseAnimator([0, -20, 20], trigger: trigger) { content, offset in
147
+ content.offset(x: offset)
148
+ } animation: { phase in
149
+ switch phase {
150
+ case -20: .bouncy
151
+ case 20: .linear
152
+ default: .smooth
153
+ }
154
+ }
155
+ ```
156
+
157
+ ### Good vs Bad
158
+
159
+ ```swift
160
+ // GOOD - use phaseAnimator for multi-step sequences
161
+ .phaseAnimator([0, -10, 10, 0], trigger: trigger) { content, offset in
162
+ content.offset(x: offset)
163
+ }
164
+
165
+ // BAD - manual DispatchQueue sequencing
166
+ Button("Animate") {
167
+ withAnimation(.easeOut(duration: 0.1)) { offset = -10 }
168
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
169
+ withAnimation { offset = 10 }
170
+ }
171
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
172
+ withAnimation { offset = 0 }
173
+ }
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Keyframe Animations (iOS 17+)
180
+
181
+ Precise timing control with exact values at specific times.
182
+
183
+ ### Basic Usage
184
+
185
+ ```swift
186
+ Button("Bounce") { trigger += 1 }
187
+ .keyframeAnimator(
188
+ initialValue: AnimationValues(),
189
+ trigger: trigger
190
+ ) { content, value in
191
+ content
192
+ .scaleEffect(value.scale)
193
+ .offset(y: value.verticalOffset)
194
+ } keyframes: { _ in
195
+ KeyframeTrack(\.scale) {
196
+ SpringKeyframe(1.2, duration: 0.15)
197
+ SpringKeyframe(0.9, duration: 0.1)
198
+ SpringKeyframe(1.0, duration: 0.15)
199
+ }
200
+ KeyframeTrack(\.verticalOffset) {
201
+ LinearKeyframe(-20, duration: 0.15)
202
+ LinearKeyframe(0, duration: 0.25)
203
+ }
204
+ }
205
+
206
+ struct AnimationValues {
207
+ var scale: CGFloat = 1.0
208
+ var verticalOffset: CGFloat = 0
209
+ }
210
+ ```
211
+
212
+ ### Keyframe Types
213
+
214
+ | Type | Behavior |
215
+ |------|----------|
216
+ | `CubicKeyframe` | Smooth interpolation |
217
+ | `LinearKeyframe` | Straight-line interpolation |
218
+ | `SpringKeyframe` | Spring physics |
219
+ | `MoveKeyframe` | Instant jump (no interpolation) |
220
+
221
+ ### Multiple Synchronized Tracks
222
+
223
+ Tracks run **in parallel**, each animating one property.
224
+
225
+ ```swift
226
+ // GOOD - bell shake with synchronized rotation and scale
227
+ struct BellAnimation {
228
+ var rotation: Double = 0
229
+ var scale: CGFloat = 1.0
230
+ }
231
+
232
+ Image(systemName: "bell.fill")
233
+ .keyframeAnimator(
234
+ initialValue: BellAnimation(),
235
+ trigger: trigger
236
+ ) { content, value in
237
+ content
238
+ .rotationEffect(.degrees(value.rotation))
239
+ .scaleEffect(value.scale)
240
+ } keyframes: { _ in
241
+ KeyframeTrack(\.rotation) {
242
+ CubicKeyframe(15, duration: 0.1)
243
+ CubicKeyframe(-15, duration: 0.1)
244
+ CubicKeyframe(10, duration: 0.1)
245
+ CubicKeyframe(-10, duration: 0.1)
246
+ CubicKeyframe(0, duration: 0.1)
247
+ }
248
+ KeyframeTrack(\.scale) {
249
+ CubicKeyframe(1.1, duration: 0.25)
250
+ CubicKeyframe(1.0, duration: 0.25)
251
+ }
252
+ }
253
+
254
+ // BAD - manual timer-based animation
255
+ Image(systemName: "bell.fill")
256
+ .onTapGesture {
257
+ withAnimation(.easeOut(duration: 0.1)) { rotation = 15 }
258
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
259
+ withAnimation { rotation = -15 }
260
+ }
261
+ // ... more manual timing - error prone
262
+ }
263
+ ```
264
+
265
+ ### KeyframeTimeline (iOS 17+)
266
+
267
+ Query animation values directly for testing or non-SwiftUI use.
268
+
269
+ ```swift
270
+ let timeline = KeyframeTimeline(initialValue: AnimationValues()) {
271
+ KeyframeTrack(\.scale) {
272
+ CubicKeyframe(1.2, duration: 0.25)
273
+ CubicKeyframe(1.0, duration: 0.25)
274
+ }
275
+ }
276
+
277
+ let midpoint = timeline.value(time: 0.25)
278
+ print(midpoint.scale) // Value at 0.25 seconds
279
+ ```
280
+
281
+ ---
282
+
283
+ ## Animation Completion Handlers (iOS 17+)
284
+
285
+ Execute code when animations finish.
286
+
287
+ ### With withAnimation
288
+
289
+ ```swift
290
+ // GOOD - completion with withAnimation
291
+ Button("Animate") {
292
+ withAnimation(.spring) {
293
+ isExpanded.toggle()
294
+ } completion: {
295
+ showNextStep = true
296
+ }
297
+ }
298
+ ```
299
+
300
+ ### With Transaction (For Reexecution)
301
+
302
+ ```swift
303
+ // GOOD - completion fires on every trigger change
304
+ Circle()
305
+ .scaleEffect(bounceCount % 2 == 0 ? 1.0 : 1.2)
306
+ .transaction(value: bounceCount) { transaction in
307
+ transaction.animation = .spring
308
+ transaction.addAnimationCompletion {
309
+ message = "Bounce \(bounceCount) complete"
310
+ }
311
+ }
312
+
313
+ // BAD - completion only fires ONCE (no value parameter)
314
+ Circle()
315
+ .scaleEffect(bounceCount % 2 == 0 ? 1.0 : 1.2)
316
+ .animation(.spring, value: bounceCount)
317
+ .transaction { transaction in // No value!
318
+ transaction.addAnimationCompletion {
319
+ completionCount += 1 // Only fires once, ever
320
+ }
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ## @Animatable Macro (iOS 26+)
327
+
328
+ The `@Animatable` macro auto-synthesizes `animatableData` from all animatable stored properties, eliminating verbose manual conformance. Use `@AnimatableIgnored` to exclude properties that should not animate.
329
+
330
+ ### Before (Manual)
331
+
332
+ ```swift
333
+ struct Wedge: Shape {
334
+ var startAngle: Angle
335
+ var endAngle: Angle
336
+ var drawClockwise: Bool
337
+
338
+ var animatableData: AnimatablePair<Double, Double> {
339
+ get { AnimatablePair(startAngle.radians, endAngle.radians) }
340
+ set {
341
+ startAngle = .radians(newValue.first)
342
+ endAngle = .radians(newValue.second)
343
+ }
344
+ }
345
+
346
+ func path(in rect: CGRect) -> Path { /* ... */ }
347
+ }
348
+ ```
349
+
350
+ ### After (@Animatable)
351
+
352
+ ```swift
353
+ @Animatable
354
+ struct Wedge: Shape {
355
+ var startAngle: Angle
356
+ var endAngle: Angle
357
+ @AnimatableIgnored var drawClockwise: Bool
358
+
359
+ func path(in rect: CGRect) -> Path { /* ... */ }
360
+ }
361
+ ```
362
+
363
+ ### When to Use
364
+ - **Prefer `@Animatable`** for any custom `Shape`, `AnimatableModifier`, or type conforming to `Animatable` with multiple properties
365
+ - **Use `@AnimatableIgnored`** for properties that control behavior but should not interpolate (e.g., directions, flags, identifiers)
366
+ - The macro works with any type conforming to `Animatable`, not just `Shape`
367
+
368
+ > Source: "What's new in SwiftUI" (WWDC25, session 256)
369
+
370
+ ---
371
+
372
+ ## Quick Reference
373
+
374
+ ### Transactions (All iOS versions)
375
+ - `withTransaction` is the explicit form of `withAnimation`
376
+ - Implicit animations override explicit (later in view tree wins)
377
+ - Use `disablesAnimations` to prevent override
378
+ - Use `.transaction { $0.animation = nil }` to remove animation
379
+
380
+ ### Custom Transaction Keys (iOS 17+)
381
+ - Pass metadata through animation system via `TransactionKey`
382
+
383
+ ### Phase Animations (iOS 17+)
384
+ - Use for multi-step sequences returning to start
385
+ - Prefer enum phases for clarity
386
+ - Each phase change is a separate animation
387
+ - Use `trigger` parameter for one-shot animations
388
+
389
+ ### Keyframe Animations (iOS 17+)
390
+ - Use for precise timing control
391
+ - Tracks run in parallel
392
+ - Use `KeyframeTimeline` for testing/advanced use
393
+ - Prefer over manual DispatchQueue timing
394
+
395
+ ### Completion Handlers (iOS 17+)
396
+ - Use `withAnimation(.animation) { } completion: { }` for one-shot completion handlers
397
+ - Use `.transaction(value:)` for handlers that should refire on every value change
398
+ - Without `value:` parameter, completion only fires once
399
+
400
+ ### @Animatable Macro (iOS 26+)
401
+ - Use `@Animatable` to auto-synthesize `animatableData` from stored properties
402
+ - Use `@AnimatableIgnored` to exclude non-animatable properties
403
+ - Replaces verbose manual `animatableData` getters/setters