@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +285 -285
  5. package/package.json +3 -3
  6. package/pipeline/lib/redact.mjs +3 -2
  7. package/pipeline/scripts/_notices.mjs +1 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +13 -1
  9. package/pipeline/scripts/pre-commit-check.sh +4 -0
  10. package/pipeline/skills/.skill-manifest.json +69 -69
  11. package/pipeline/skills/shared/README.md +70 -70
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  16. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  17. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  18. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  19. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  20. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  21. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  22. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  23. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +345 -277
  24. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  25. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +107 -121
  26. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +145 -165
  27. package/pipeline/skills/shared/external/app-store-review/SKILL.md +306 -326
  28. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  29. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  30. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  31. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +335 -360
  32. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  34. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  35. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  37. package/pipeline/skills/shared/external/authentication/SKILL.md +277 -381
  38. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  39. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +135 -178
  40. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  41. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  42. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  43. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  44. package/pipeline/skills/shared/external/background-processing/SKILL.md +274 -384
  45. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  46. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +173 -321
  47. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  48. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  49. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  50. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  51. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  52. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  53. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  54. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  55. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  56. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +228 -376
  57. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  58. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  59. package/pipeline/skills/shared/external/core-data/SKILL.md +302 -368
  60. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  61. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  62. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  63. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  64. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  65. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  66. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  67. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  68. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  69. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  70. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  71. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  72. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  73. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  74. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  75. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  76. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  77. package/pipeline/skills/shared/external/device-integrity/SKILL.md +236 -353
  78. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  79. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  80. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  81. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  82. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  83. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  84. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  85. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  86. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  87. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  88. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  89. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  90. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  91. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  92. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  93. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  94. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  95. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  96. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  97. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  98. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  99. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  100. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  101. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  102. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  103. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  104. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  105. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  106. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  107. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  108. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  109. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  111. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  112. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  113. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  114. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
  115. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +1 -1
  116. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +8 -7
  117. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
  118. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +5 -2
  119. package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +100 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +45 -26
  121. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +14 -16
  122. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +12 -5
  123. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +2 -1
  124. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +6 -5
  125. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +44 -18
  126. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +5 -2
  127. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +10 -11
  128. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +4 -33
  129. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +12 -59
  130. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +297 -267
  131. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  132. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  133. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  134. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  135. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  136. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  137. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  138. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  139. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  140. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  141. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  142. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  143. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  144. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  145. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  146. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  147. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  148. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  149. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  150. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  151. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  152. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  153. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  154. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  155. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  156. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  157. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  158. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  159. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  160. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  161. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  162. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  163. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  164. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  165. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  166. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  167. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  168. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  169. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  170. package/pipeline/skills/shared/external/skill-creator/template.md +7 -1
  171. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  172. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  173. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  174. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  175. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  176. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  177. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +302 -241
  178. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  179. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  180. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  181. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  182. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  183. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  184. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  185. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  186. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  187. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  188. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  189. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  191. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +304 -351
  193. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  194. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  195. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  196. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  197. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  198. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  199. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  200. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  201. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  202. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  203. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  204. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  205. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  206. package/pipeline/skills/shared/external/swift-security/SKILL.md +183 -162
  207. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  208. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  209. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +411 -476
  210. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  211. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  212. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  213. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  214. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  215. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  216. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +375 -491
  217. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  218. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  219. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  220. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +397 -457
  221. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  222. package/pipeline/skills/shared/external/swift-testing/SKILL.md +191 -175
  223. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  224. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +81 -84
  225. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  226. package/pipeline/skills/shared/external/swiftdata/SKILL.md +394 -256
  227. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  228. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  229. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  230. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  231. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  232. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  233. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  234. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  235. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  236. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  237. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  238. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  239. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  240. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  241. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  242. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  243. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  244. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  245. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  246. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  247. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  248. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  249. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  250. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  251. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +201 -168
  252. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  253. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +134 -133
  254. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  255. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +111 -138
  256. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  257. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  258. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  259. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  260. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  261. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  262. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  263. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  264. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  265. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  266. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  267. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  268. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  269. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  270. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  271. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  272. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  273. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  274. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  275. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  276. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  277. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  278. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  279. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  280. package/pipeline/skills/shared/external/weatherkit/SKILL.md +160 -315
  281. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  282. package/pipeline/skills/shared/external/widgetkit/SKILL.md +224 -288
  283. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +416 -719
  284. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,169 +1,204 @@
1
- # Sheets
1
+ # Sheet Routing
2
2
 
3
- ## Contents
3
+ Part of the `swiftui-navigation` skill. Routing every modal through one place
4
+ lets any view open a sheet without threading bindings through its parents, and
5
+ it keeps working as screens are added.
4
6
 
5
- - [Intent](#intent)
6
- - [Core architecture](#core-architecture)
7
- - [Example: SheetDestination enum](#example-sheetdestination-enum)
8
- - [Example: withSheetDestinations modifier](#example-withsheetdestinations-modifier)
9
- - [Example: presenting from a child view](#example-presenting-from-a-child-view)
10
- - [Required wiring](#required-wiring)
11
- - [Example: sheets that need their own navigation](#example-sheets-that-need-their-own-navigation)
12
- - [Design choices to keep](#design-choices-to-keep)
13
- - [iOS 26 Presentation Sizing](#ios-26-presentation-sizing)
14
- - [Pitfalls](#pitfalls)
7
+ ## Building blocks
15
8
 
16
- ## Intent
9
+ - A `SheetDestination` enum, `Identifiable`, with one case per modal.
10
+ - `presentedSheet: SheetDestination?` stored on the router.
11
+ - A modifier, here `withSheetDestinations(sheet:)`, that turns a case into its
12
+ view.
13
+ - The router in the environment, so children assign `presentedSheet` directly.
17
14
 
18
- Use a centralized sheet routing pattern so any view can present modals without prop-drilling. This keeps sheet state in one place and scales as the app grows.
19
-
20
- ## Core architecture
21
-
22
- - Define a `SheetDestination` enum that describes every modal and is `Identifiable`.
23
- - Store the current sheet in a router object (`presentedSheet: SheetDestination?`).
24
- - Create a view modifier like `withSheetDestinations(...)` that maps the enum to concrete sheet views.
25
- - Inject the router into the environment so child views can set `presentedSheet` directly.
26
-
27
- ## Example: SheetDestination enum
15
+ ## The destination enum
28
16
 
29
17
  ```swift
30
- enum SheetDestination: Identifiable, Hashable {
31
- case composer
32
- case editProfile
33
- case settings
34
- case report(itemID: String)
35
-
36
- var id: String {
37
- switch self {
38
- case .composer, .editProfile:
39
- // Use the same id to ensure only one editor-like sheet is active at a time.
40
- return "editor"
41
- case .settings:
42
- return "settings"
43
- case .report:
44
- return "report"
18
+ enum SheetDestination: Hashable, Identifiable {
19
+ case newTrip
20
+ case editTrip(Trip.ID)
21
+ case sharePhoto(Photo.ID)
22
+ case report(itemID: String)
23
+
24
+ var id: String {
25
+ if case .sharePhoto = self { return "share" }
26
+ if case .report = self { return "report" }
27
+ return "trip-editor"
45
28
  }
46
- }
47
29
  }
48
30
  ```
49
31
 
50
- ## Example: withSheetDestinations modifier
32
+ `newTrip` and `editTrip` return the same `id`. They are two ways into one
33
+ editor, so they can never be on screen together.
34
+
35
+ ## The mapping modifier
51
36
 
52
37
  ```swift
53
38
  extension View {
54
- func withSheetDestinations(
55
- sheet: Binding<SheetDestination?>
56
- ) -> some View {
57
- sheet(item: sheet) { destination in
58
- Group {
59
- switch destination {
60
- case .composer:
61
- ComposerView()
62
- case .editProfile:
63
- EditProfileView()
64
- case .settings:
65
- SettingsView()
66
- case .report(let itemID):
67
- ReportView(itemID: itemID)
39
+ func withSheetDestinations(sheet: Binding<SheetDestination?>) -> some View {
40
+ self.sheet(item: sheet) { modal in
41
+ Group {
42
+ switch modal {
43
+ case .newTrip: TripEditor(trip: nil)
44
+ case .editTrip(let id): TripEditor(tripID: id)
45
+ case .sharePhoto(let id): PhotoShareView(photoID: id)
46
+ case .report(let itemID): ReportForm(itemID: itemID)
47
+ }
48
+ }
68
49
  }
69
- }
70
50
  }
71
- }
72
51
  }
73
52
  ```
74
53
 
75
- ## Example: presenting from a child view
54
+ ## Opening a sheet from deep in the tree
76
55
 
77
56
  ```swift
78
- struct StatusRow: View {
79
- @Environment(RouterPath.self) private var router
80
-
81
- var body: some View {
82
- Button("Report") {
83
- router.presentedSheet = .report(itemID: "123")
57
+ struct CommentRow: View {
58
+ @Environment(Router.self) private var router
59
+ let comment: Comment
60
+
61
+ var body: some View {
62
+ Text(comment.body)
63
+ .contextMenu {
64
+ Button("Report", systemImage: "flag") {
65
+ router.presentedSheet = .report(itemID: comment.id)
66
+ }
67
+ }
84
68
  }
85
- }
86
69
  }
87
70
  ```
88
71
 
89
- ## Required wiring
72
+ ## Wiring at the root
73
+
74
+ 1. The parent owns the router instance.
75
+ 2. It installs `withSheetDestinations(sheet: $router.presentedSheet)`; a plain
76
+ `sheet(item:)` does the same job.
77
+ 3. `.environment(router)` comes later in the chain than the sheet modifier, so
78
+ whatever the sheet shows can read the router as well.
90
79
 
91
- For the child view to work, a parent view must:
92
- - own the router instance,
93
- - attach `withSheetDestinations(sheet: $router.presentedSheet)` (or an equivalent `sheet(item:)` handler), and
94
- - inject it with `.environment(router)` after the sheet modifier so the modal content inherits it.
80
+ ```swift
81
+ struct TripsRoot: View {
82
+ @State private var router = Router()
83
+
84
+ var body: some View {
85
+ NavigationStack(path: $router.path) { TripsList().withAppRouter() }
86
+ .withSheetDestinations(sheet: $router.presentedSheet)
87
+ .environment(router)
88
+ }
89
+ }
90
+ ```
95
91
 
96
- This makes the child assignment to `router.presentedSheet` drive presentation at the root.
92
+ With that in place, a child that sets `presentedSheet` makes the root present
93
+ the sheet.
97
94
 
98
- ## Example: sheets that need their own navigation
95
+ ## Sheets that push their own screens
99
96
 
100
- Wrap sheet content in a `NavigationStack` so it can push within the modal.
97
+ Wrap the content in a stack with a close button when a sheet needs its own
98
+ navigation.
101
99
 
102
100
  ```swift
103
101
  struct NavigationSheet<Content: View>: View {
104
- var content: () -> Content
105
-
106
- var body: some View {
107
- NavigationStack {
108
- content()
109
- .toolbar { CloseToolbarItem() }
102
+ @ViewBuilder var content: Content
103
+ @Environment(\.dismiss) private var close
104
+
105
+ var body: some View {
106
+ NavigationStack {
107
+ content
108
+ .toolbar {
109
+ ToolbarItem(placement: .cancellationAction) {
110
+ Button("Close", systemImage: "xmark") { close() }
111
+ }
112
+ }
113
+ }
110
114
  }
111
- }
112
115
  }
113
116
  ```
114
117
 
115
- ## Design choices to keep
118
+ ## Rules worth keeping
116
119
 
117
- - Centralize sheet routing so features can present modals without wiring bindings through many layers.
118
- - Use `sheet(item:)` to guarantee a single sheet is active and to drive presentation from the enum.
119
- - Group related sheets under the same `id` when they are mutually exclusive (e.g., editor flows).
120
- - Keep sheet views lightweight and composed from smaller views; avoid large monoliths.
120
+ - Route sheets centrally so features do not pass bindings through layers.
121
+ - `sheet(item:)` keeps exactly one sheet active, chosen by the enum.
122
+ - Mutually exclusive sheets share an `id`.
123
+ - Sheet views stay small and composed from pieces.
121
124
 
122
- ## iOS 26 Presentation Sizing
125
+ ## Presentation sizing
123
126
 
124
- Control sheet dimensions with `presentationSizing(_:)` (iOS 18+):
127
+ The section concerns iOS 26 layouts, but `presentationSizing(_:)` itself is
128
+ available from iOS 18. Values: `.automatic`, `.page`, `.form`, `.fitted`.
129
+ `.fitted(horizontal:vertical:)` fits only the axes you pass, and
130
+ `.sticky(horizontal:vertical:)` lets the sheet grow along them without
131
+ shrinking.
125
132
 
126
133
  ```swift
127
- .sheet(item: $selectedItem) { item in
128
- EditItemSheet(item: item)
129
- .presentationSizing(.form)
130
- }
134
+ TripEditor(trip: nil)
135
+ .presentationSizing(.form.sticky(horizontal: false, vertical: true))
131
136
  ```
132
137
 
133
- `PresentationSizing` values:
134
- - `.automatic` -- platform default
135
- - `.page` -- roughly paper size, for informational content
136
- - `.form` -- slightly narrower than page, for form-style UI
137
- - `.fitted` -- sized by the content's ideal size
138
+ ## Confirming dismissal
138
139
 
139
- Modifier methods for fine-tuning:
140
- - `.fitted(horizontal:vertical:)` -- constrain fitting to specific axes
141
- - `.sticky(horizontal:vertical:)` -- grow but do not shrink in specified dimensions
142
-
143
- ### Dismissal Confirmation (macOS 15+ / iOS 26+)
144
-
145
- Show a confirmation dialog when the user tries to dismiss a sheet with unsaved changes:
140
+ On iOS, block the swipe with `.interactiveDismissDisabled(_:)` while there are
141
+ unsaved edits, and ask from your own Close button with `confirmationDialog`:
146
142
 
147
143
  ```swift
148
- .sheet(item: $selectedItem) { item in
149
- EditItemSheet(item: item)
150
- .dismissalConfirmationDialog(
151
- "Discard changes?",
152
- shouldPresent: hasUnsavedChanges
153
- ) {
154
- Button("Discard", role: .destructive) { discardChanges() }
144
+ struct TripEditorSheet: View {
145
+ let id: Trip.ID
146
+ let hasEdits: Bool
147
+ let draft: Draft
148
+ @State private var confirmsDiscard = false
149
+ @Environment(\.dismiss) private var dismiss
150
+
151
+ var body: some View {
152
+ NavigationStack {
153
+ TripEditor(tripID: id)
154
+ .toolbar {
155
+ ToolbarItem(placement: .cancellationAction) {
156
+ Button("Close", systemImage: "xmark") {
157
+ if hasEdits { confirmsDiscard = true } else { dismiss() }
158
+ }
159
+ .confirmationDialog("Throw away your edits?", isPresented: $confirmsDiscard) {
160
+ Button("Throw Away", role: .destructive) {
161
+ draft.revert()
162
+ dismiss()
163
+ }
164
+ Button("Save and Close") {
165
+ draft.save()
166
+ dismiss()
167
+ }
168
+ }
169
+ }
170
+ }
155
171
  }
172
+ .interactiveDismissDisabled(hasEdits)
173
+ }
156
174
  }
157
175
  ```
158
176
 
159
- - Cancel action is included automatically and prevents dismissal
160
- - All other action buttons allow dismissal to proceed
161
- - Use `.keyboardShortcut(.defaultAction)` to set the default button
177
+ On macOS 15 and later, `dismissalConfirmationDialog(_:shouldPresent:)` does
178
+ this for you. The SDK marks it unavailable on iOS, iPadOS, tvOS, watchOS and
179
+ visionOS, so it only compiles in a macOS target:
180
+
181
+ ```swift
182
+ TripEditor(tripID: id)
183
+ .dismissalConfirmationDialog("Throw away your edits?", shouldPresent: hasEdits) {
184
+ Button("Throw Away", role: .destructive) { draft.revert() }
185
+ Button("Save and Close") { draft.save() }
186
+ .keyboardShortcut(.defaultAction)
187
+ }
188
+ ```
189
+
190
+ The system adds Cancel on its own, and Cancel keeps the sheet open. Any other
191
+ button lets the dismissal go ahead. `.keyboardShortcut(.defaultAction)` marks
192
+ the default choice.
162
193
 
163
194
  ## Pitfalls
164
195
 
165
- - Avoid mixing `sheet(isPresented:)` and `sheet(item:)` for the same concern; prefer a single enum.
166
- - Do not store heavy state inside `SheetDestination`; pass lightweight identifiers or models.
167
- - If multiple sheets can appear from the same screen, give them distinct `id` values.
168
- - Use `presentationSizing(.form)` for form sheets instead of hard-coding frame dimensions.
169
- - Always pair `dismissalConfirmationDialog` with a `shouldPresent` condition; showing it when there are no changes is confusing.
196
+ - Two presentation styles, `sheet(isPresented:)` plus `sheet(item:)`, for one
197
+ concern. A single enum is enough.
198
+ - Carrying heavy state inside `SheetDestination`. Pass identifiers or small
199
+ models.
200
+ - Reusing an `id` for sheets that may legitimately come from the same screen
201
+ one after another; give them distinct values.
202
+ - Fixed frames instead of `presentationSizing(.form)`.
203
+ - A dismissal dialog without a real `shouldPresent` condition. Asking when
204
+ nothing changed only confuses people.
@@ -1,178 +1,151 @@
1
- # TabView
1
+ # TabView Architecture
2
2
 
3
- ## Contents
3
+ Part of the `swiftui-navigation` skill. Goal: tabs that scale across platforms,
4
+ with one source of truth for what each tab is and shows, different tab sets and
5
+ sidebar groupings per platform, tabs generated from data, and a hook that can
6
+ intercept special tabs.
4
7
 
5
- - [Intent](#intent)
6
- - [Core architecture](#core-architecture)
7
- - [Example: custom binding with side effects](#example-custom-binding-with-side-effects)
8
- - [Example: direct binding without side effects](#example-direct-binding-without-side-effects)
9
- - [Design choices to keep](#design-choices-to-keep)
10
- - [Dynamic tabs pattern](#dynamic-tabs-pattern)
11
- - [iOS 26 Tab API](#ios-26-tab-api)
12
- - [Pitfalls](#pitfalls)
8
+ ## Building blocks
13
9
 
14
- ## Intent
10
+ - `AppTab` enum: identity, title, icon and a builder for its content.
11
+ - `SidebarSections` enum: which tabs appear under which sidebar heading. Give
12
+ its `title` the type `LocalizedStringKey`. With a `String` title,
13
+ `TabSection(group.title)` makes `Tab(value:)` ambiguous and the view does not
14
+ compile.
15
+ - `AppView`: owns the `TabView` and the selection, and routes selection changes
16
+ through `updateTab(with:)`.
15
17
 
16
- Use this pattern for a scalable, multi-platform tab architecture with:
17
- - a single source of truth for tab identity and content,
18
- - platform-specific tab sets and sidebar sections,
19
- - dynamic tabs sourced from data,
20
- - an interception hook for special tabs (e.g., compose).
21
-
22
- ## Core architecture
23
-
24
- - `AppTab` enum defines identity, labels, icons, and content builder.
25
- - `SidebarSections` enum groups tabs for sidebar sections.
26
- - `AppView` owns the `TabView` and selection binding, and routes tab changes through `updateTab`.
27
-
28
- ## Example: custom binding with side effects
29
-
30
- Use this when tab selection needs side effects, like intercepting a special tab to perform an action instead of changing selection.
18
+ ## Selection with side effects
31
19
 
32
20
  ```swift
33
- @MainActor
34
21
  struct AppView: View {
35
- @Binding var selectedTab: AppTab
36
-
37
- var body: some View {
38
- TabView(selection: .init(
39
- get: { selectedTab },
40
- set: { updateTab(with: $0) }
41
- )) {
42
- ForEach(availableSections) { section in
43
- TabSection(section.title) {
44
- ForEach(section.tabs) { tab in
45
- Tab(value: tab) {
46
- tab.makeContentView(
47
- homeTimeline: $timeline,
48
- selectedTab: $selectedTab,
49
- pinnedFilters: $pinnedFilters
50
- )
51
- } label: {
52
- tab.label
53
- }
54
- .tabPlacement(tab.tabPlacement)
55
- }
56
- }
57
- .tabPlacement(.sidebarOnly)
58
- }
59
- }
60
- }
22
+ let sections: [SidebarSections]
23
+ @State private var scrollTarget: AppTab?
24
+ @State private var showsComposer = false
25
+ @State private var selectedTab: AppTab = .home
61
26
 
62
- private func updateTab(with newTab: AppTab) {
63
- if newTab == .post {
64
- // Intercept special tabs (compose) instead of changing selection.
65
- presentComposer()
66
- return
27
+ private var selection: Binding<AppTab> {
28
+ Binding(get: { selectedTab }, set: updateTab(with:))
67
29
  }
68
- selectedTab = newTab
69
- }
70
- }
71
- ```
72
-
73
- ## Example: direct binding without side effects
74
30
 
75
- Use this when selection is purely state-driven.
76
-
77
- ```swift
78
- @MainActor
79
- struct AppView: View {
80
- @Binding var selectedTab: AppTab
81
-
82
- var body: some View {
83
- TabView(selection: $selectedTab) {
84
- ForEach(availableSections) { section in
85
- TabSection(section.title) {
86
- ForEach(section.tabs) { tab in
87
- Tab(value: tab) {
88
- tab.makeContentView(
89
- homeTimeline: $timeline,
90
- selectedTab: $selectedTab,
91
- pinnedFilters: $pinnedFilters
92
- )
93
- } label: {
94
- tab.label
31
+ var body: some View {
32
+ TabView(selection: selection) {
33
+ ForEach(sections) { group in
34
+ TabSection(group.title) {
35
+ ForEach(group.tabs) { entry in
36
+ Tab(value: entry) {
37
+ entry.makeContentView(scrollTarget: $scrollTarget)
38
+ } label: {
39
+ entry.label
40
+ }
41
+ .tabPlacement(entry.tabPlacement)
42
+ }
43
+ }
44
+ .tabPlacement(.sidebarOnly)
95
45
  }
96
- .tabPlacement(tab.tabPlacement)
97
- }
98
46
  }
99
- .tabPlacement(.sidebarOnly)
100
- }
47
+ .sheet(isPresented: $showsComposer) { ComposerView() }
48
+ }
49
+
50
+ private func updateTab(with next: AppTab) {
51
+ if next == .post {
52
+ showsComposer = true
53
+ return
54
+ }
55
+ if next == selectedTab {
56
+ scrollTarget = next
57
+ }
58
+ selectedTab = next
101
59
  }
102
- }
103
60
  }
104
61
  ```
105
62
 
106
- ## Design choices to keep
63
+ Choosing `.post` opens the composer and leaves the selection where it was.
64
+ Choosing the current tab again asks it to scroll to the top.
107
65
 
108
- - Centralize tab identity and content in `AppTab` with `makeContentView(...)`.
109
- - Use `Tab(value:)` with `selection` binding for state-driven tab selection.
110
- - Route selection changes through `updateTab` to handle special tabs and scroll-to-top behavior.
111
- - Use `TabSection` + `.tabPlacement(.sidebarOnly)` for sidebar structure.
112
- - Use `.tabPlacement(.pinned)` in `AppTab.tabPlacement` for a single pinned tab; this is commonly used for iOS 26 `.searchable` tab content, but can be used for any tab.
66
+ ## Selection without side effects
113
67
 
114
- ## Dynamic tabs pattern
68
+ If selection is pure state, bind directly: `TabView(selection: $selectedTab)`
69
+ with the same `TabSection` and `Tab` structure inside.
115
70
 
116
- - `SidebarSections` handles dynamic data tabs.
117
- - `AppTab.anyTimelineFilter(filter:)` wraps dynamic tabs in a single enum case.
118
- - The enum provides label/icon/title for dynamic tabs via the filter type.
71
+ ## Rules worth keeping
119
72
 
120
- ## iOS 26 Tab API
73
+ - `AppTab` is the single home for identity and content, through
74
+ `makeContentView(...)`.
75
+ - Tabs use `Tab(value:)` together with a selection binding.
76
+ - Selection goes through `updateTab(with:)`; that one function deals with
77
+ compose-style tabs and with re-tapping to scroll up.
78
+ - Sidebar structure comes from `TabSection` plus `.tabPlacement(.sidebarOnly)`.
79
+ - `.tabPlacement(.pinned)` keeps one tab fixed in place. It is typical for an
80
+ iOS 26 `.searchable` tab but works for any tab.
121
81
 
122
- iOS 26 expands the Tab API with minimize behavior, roles, and accessory placements.
82
+ ## Tabs generated from data
123
83
 
124
- ### Tab Bar Minimization
84
+ `SidebarSections` can hold tabs that come from user data, such as saved
85
+ filters. Represent them with one case that carries a payload, for example
86
+ `AppTab.savedFilter(SavedFilter)`, and read the title and icon from the filter.
125
87
 
126
88
  ```swift
127
- TabView(selection: $selectedTab) {
128
- // tabs
129
- }
130
- .tabBarMinimizeBehavior(.onScrollDown) // iPhone only
131
- ```
132
-
133
- `TabBarMinimizeBehavior` values:
134
- - `.automatic` -- determine behavior from context
135
- - `.onScrollDown` -- minimize when user scrolls down (iPhone only)
136
- - `.onScrollUp` -- minimize when user scrolls up (iPhone only)
137
- - `.never` -- never minimize the tab bar
89
+ enum AppTab: Hashable, Identifiable {
90
+ case home, search, post, profile
91
+ case savedFilter(SavedFilter)
138
92
 
139
- ### Tab Search Role
140
-
141
- Replace the tab bar with a search field when the search tab is active:
93
+ var id: String {
94
+ guard case .savedFilter(let filter) = self else { return String(describing: self) }
95
+ return "filter-\(filter.id)"
96
+ }
142
97
 
143
- ```swift
144
- Tab(role: .search) {
145
- SearchView()
98
+ @ViewBuilder var label: some View {
99
+ switch self {
100
+ case .savedFilter(let filter): Label(filter.name, systemImage: filter.symbol)
101
+ case .home: Label("Start", systemImage: "house")
102
+ case .search: Label("Search", systemImage: "magnifyingglass")
103
+ case .post: Label("Post", systemImage: "square.and.pencil")
104
+ case .profile: Label("Profile", systemImage: "person")
105
+ }
106
+ }
146
107
  }
147
108
  ```
148
109
 
149
- ### Sidebar Customization
110
+ ## Tab APIs from iOS 18 and iOS 26
150
111
 
151
112
  ```swift
152
113
  TabView {
153
- // tabs
114
+ Tab("Feed", systemImage: "list.bullet") { FeedView() }
115
+ Tab(role: .search) { SearchView() }
154
116
  }
155
- .tabViewSidebarHeader { SidebarHeaderView() }
156
- .tabViewSidebarFooter { SidebarFooterView() }
157
- .tabViewSidebarBottomBar { BottomBarView() }
117
+ .tabBarMinimizeBehavior(.onScrollDown)
118
+ .tabViewBottomAccessory { MiniPlayerBar() }
119
+ .tabViewSidebarHeader { AccountHeader() }
120
+ .tabViewSidebarFooter { StorageFooter() }
121
+ .tabViewSidebarBottomBar { SettingsButton() }
158
122
  ```
159
123
 
160
- ### Bottom Accessory
124
+ iOS 18 (macOS 15, visionOS 2):
161
125
 
162
- Use `TabViewBottomAccessoryPlacement` for content below the tab bar:
126
+ - `Tab(role: .search)` marks the search tab; the iOS 26 tab bar replaces the bar
127
+ with a search field while that tab is active.
128
+ - Sidebar customisation: `.tabViewSidebarHeader { }`,
129
+ `.tabViewSidebarFooter { }` and `.tabViewSidebarBottomBar { }`.
130
+ - `TabSection` and `.tabPlacement(_:)`.
163
131
 
164
- ```swift
165
- TabView {
166
- // tabs
167
- }
168
- .tabViewBottomAccessory { NowPlayingBar() }
169
- ```
132
+ iOS 26 only:
133
+
134
+ - `TabBarMinimizeBehavior`: `.automatic` (decided by context), `.onScrollDown`,
135
+ `.onScrollUp` and `.never`. The two scroll behaviours apply on iPhone only.
136
+ - `.tabViewBottomAccessory { }` shows content just above the tab bar; its
137
+ placement is described by `TabViewBottomAccessoryPlacement`.
138
+
139
+ The example mixes both groups, so as written it needs iOS 26.
170
140
 
171
141
  ## Pitfalls
172
142
 
173
- - Avoid adding ViewModels for tabs; keep state local or in `@Observable` services.
174
- - Do not nest `@Observable` objects inside other `@Observable` objects.
175
- - Ensure `AppTab.id` values are stable; dynamic cases should hash on stable IDs.
176
- - Special tabs (compose) should not change selection.
177
- - Prefer `Tab(value:)` with `TabView(selection:)` over the older `.tabItem { }` API for typed tab selection.
178
- - `tabBarMinimizeBehavior` only works on iPhone; it has no effect on iPad or Mac.
143
+ - A view model per tab. Keep state local to views or in shared `@Observable`
144
+ services.
145
+ - An `AppTab.id` that changes between launches; dynamic cases must hash on a
146
+ stable identifier.
147
+ - Special tabs such as compose that change the selection.
148
+ - `.tabItem { }` instead of `Tab(value:)` with `TabView(selection:)`, which
149
+ loses typed selection.
150
+ - Expecting `tabBarMinimizeBehavior` to work on iPad or Mac; it does nothing
151
+ there.