@mmerterden/multi-agent-pipeline 20.7.0 → 20.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.
- package/CHANGELOG.md +9 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +266 -267
- package/package.json +2 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +68 -68
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,117 +1,147 @@
|
|
|
1
1
|
# Media Accessibility
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Back to [SKILL.md](../SKILL.md).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
How to make audio and video accessible with AVFoundation: tagging and choosing
|
|
6
|
+
caption and audio-description tracks, following system settings, and building
|
|
7
|
+
player controls that assistive technologies can use.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
- [SwiftUI VideoPlayer](#swiftui-videoplayer)
|
|
9
|
-
- [Custom Player Controls](#custom-player-controls)
|
|
9
|
+
## Captions, SDH and subtitles
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
AVFoundation marks accessibility-related tracks with media characteristics
|
|
12
|
+
(`AVMediaCharacteristic`,
|
|
13
|
+
https://developer.apple.com/documentation/avfoundation/avmediacharacteristic).
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
| Characteristic | Meaning |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `.transcribesSpokenDialogForAccessibility` | Text of what is said, as captions or SDH, for viewers who are deaf or hard of hearing |
|
|
18
|
+
| `.describesMusicAndSoundForAccessibility` | The text track also covers music and sound effects, not just speech |
|
|
19
|
+
| `.describesVideoForAccessibility` | An audio track that narrates the picture for viewers who are blind or have low vision |
|
|
20
|
+
| `.easyToRead` | Captions written in simpler language, for cognitive accessibility |
|
|
21
|
+
| `.containsOnlyForcedSubtitles` | Only the forced lines, shown where the content's language differs from the device's |
|
|
22
|
+
| `.languageTranslation` | Subtitles translating speech into another language |
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Docs: [AVMediaCharacteristic](https://sosumi.ai/documentation/avfoundation/avmediacharacteristic)
|
|
18
|
-
|
|
19
|
-
| Characteristic | Purpose |
|
|
20
|
-
| -------------- | ------- |
|
|
21
|
-
| `.transcribesSpokenDialogForAccessibility` | Captions/SDH - transcribes dialog for deaf or hard of hearing users |
|
|
22
|
-
| `.describesMusicAndSoundForAccessibility` | Captions that include descriptions of music and sound effects |
|
|
23
|
-
| `.describesVideoForAccessibility` | Audio descriptions - narrates visual content for blind or low-vision users |
|
|
24
|
-
| `.easyToRead` | Simplified captions for cognitive accessibility |
|
|
25
|
-
| `.containsOnlyForcedSubtitles` | Subtitles that display only when content differs from the device language |
|
|
26
|
-
| `.languageTranslation` | Subtitles providing a language translation |
|
|
27
|
-
|
|
28
|
-
### Selecting Accessible Media
|
|
24
|
+
## Picking an accessible caption track
|
|
29
25
|
|
|
30
26
|
```swift
|
|
31
27
|
import AVFoundation
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
@MainActor
|
|
30
|
+
func makeCaptionedItem(for movieURL: URL) async throws -> AVPlayerItem {
|
|
31
|
+
let movie = AVURLAsset(url: movieURL)
|
|
32
|
+
let item = AVPlayerItem(asset: movie)
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
guard let legible = try await movie.loadMediaSelectionGroup(for: .legible) else {
|
|
35
|
+
return item
|
|
36
|
+
}
|
|
37
|
+
let sdhOptions = AVMediaSelectionGroup.mediaSelectionOptions(
|
|
38
|
+
from: legible.options,
|
|
39
|
+
withMediaCharacteristics: [.transcribesSpokenDialogForAccessibility]
|
|
41
40
|
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
let playerItem = AVPlayerItem(asset: asset)
|
|
45
|
-
playerItem.select(ccOption, in: group)
|
|
41
|
+
if let sdh = sdhOptions.first {
|
|
42
|
+
item.select(sdh, in: legible)
|
|
46
43
|
}
|
|
44
|
+
return item
|
|
47
45
|
}
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
|
|
48
|
+
`AVPlayerItem` is a main-actor class. Its `select(_:in:)` is exempt only when
|
|
49
|
+
the deployment target is iOS 16 or later, so the function is `@MainActor` to
|
|
50
|
+
build for older targets too.
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
let adGroup = try await asset.load(.mediaSelectionGroup(forMediaCharacteristic: .audible))
|
|
52
|
+
## Picking an audio description track
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
let adOptions = AVMediaSelectionGroup.mediaSelectionOptions(
|
|
57
|
-
from: adGroup.options,
|
|
58
|
-
with: .describesVideoForAccessibility
|
|
59
|
-
)
|
|
54
|
+
Same approach on the audible group:
|
|
60
55
|
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
```swift
|
|
57
|
+
@MainActor
|
|
58
|
+
func enableAudioDescription(on item: AVPlayerItem, source: AVAsset) async throws {
|
|
59
|
+
guard let audible = try await source.loadMediaSelectionGroup(for: .audible) else { return }
|
|
60
|
+
let described = AVMediaSelectionGroup.mediaSelectionOptions(
|
|
61
|
+
from: audible.options,
|
|
62
|
+
withMediaCharacteristics: [.describesVideoForAccessibility]
|
|
63
|
+
)
|
|
64
|
+
if let track = described.first {
|
|
65
|
+
item.select(track, in: audible)
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
## Following the system settings
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
When a user turns on captions or audio descriptions in Settings >
|
|
73
|
+
Accessibility > Subtitles & Captioning, `AVPlayer` picks matching tracks on its
|
|
74
|
+
own. Select options by hand only when you build your own media-selection UI.
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
To read the caption preference yourself:
|
|
74
77
|
|
|
75
78
|
```swift
|
|
76
79
|
import MediaAccessibility
|
|
77
80
|
|
|
78
|
-
let
|
|
81
|
+
let displayType = MACaptionAppearanceGetDisplayType(.user)
|
|
82
|
+
let captionsShowByDefault = displayType == .alwaysOn || displayType == .automatic
|
|
79
83
|
```
|
|
80
84
|
|
|
81
|
-
|
|
85
|
+
UIKit apps can also check `UIAccessibility.isClosedCaptioningEnabled` and
|
|
86
|
+
observe `UIAccessibility.closedCaptioningStatusDidChangeNotification`.
|
|
82
87
|
|
|
83
|
-
SwiftUI
|
|
84
|
-
|
|
88
|
+
## SwiftUI `VideoPlayer`
|
|
89
|
+
|
|
90
|
+
`VideoPlayer` from AVKit wraps `AVPlayer`, so it gets the same automatic track
|
|
91
|
+
selection.
|
|
85
92
|
|
|
86
93
|
```swift
|
|
87
94
|
import AVKit
|
|
88
95
|
import SwiftUI
|
|
89
96
|
|
|
90
|
-
struct
|
|
91
|
-
let
|
|
97
|
+
struct LessonPlayer: View {
|
|
98
|
+
let lessonPlayer: AVPlayer
|
|
99
|
+
let lessonTitle: String
|
|
92
100
|
|
|
93
101
|
var body: some View {
|
|
94
|
-
VideoPlayer(player:
|
|
95
|
-
.accessibilityLabel("
|
|
96
|
-
.accessibilityHint("
|
|
102
|
+
VideoPlayer(player: lessonPlayer)
|
|
103
|
+
.accessibilityLabel("Video: \(lessonTitle)")
|
|
104
|
+
.accessibilityHint("Plays or pauses the lesson")
|
|
97
105
|
}
|
|
98
106
|
}
|
|
99
107
|
```
|
|
100
108
|
|
|
101
|
-
## Custom
|
|
109
|
+
## Custom player controls
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
A custom transport bar has to provide what the system player gives you for
|
|
112
|
+
free:
|
|
104
113
|
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
114
|
+
- play/pause, seek and volume are focusable and labelled;
|
|
115
|
+
- current time and duration are spoken when focus reaches them;
|
|
116
|
+
- a captions toggle exists and is labelled;
|
|
117
|
+
- the scrubber reports the time position through `accessibilityValue`;
|
|
118
|
+
- controls stay visible and reachable while captions are on screen.
|
|
110
119
|
|
|
111
120
|
```swift
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
struct CaptionsButton: View {
|
|
122
|
+
@Binding var captionsOn: Bool
|
|
123
|
+
|
|
124
|
+
var body: some View {
|
|
125
|
+
Button(action: { captionsOn.toggle() }) {
|
|
126
|
+
Image(systemName: "captions.bubble")
|
|
127
|
+
.symbolVariant(captionsOn ? .fill : .none)
|
|
128
|
+
}
|
|
129
|
+
.accessibilityLabel(captionsOn ? "Captions on" : "Captions off")
|
|
130
|
+
.accessibilityHint("Turns subtitles and captions on or off")
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
struct Scrubber: View {
|
|
135
|
+
@Binding var position: Double // seconds
|
|
136
|
+
let duration: Double
|
|
137
|
+
|
|
138
|
+
var body: some View {
|
|
139
|
+
Slider(value: $position, in: 0...duration)
|
|
140
|
+
.accessibilityLabel("Playback position")
|
|
141
|
+
.accessibilityValue(
|
|
142
|
+
"\(Duration.seconds(position).formatted(.time(pattern: .minuteSecond))) of "
|
|
143
|
+
+ "\(Duration.seconds(duration).formatted(.time(pattern: .minuteSecond)))"
|
|
144
|
+
)
|
|
145
|
+
}
|
|
114
146
|
}
|
|
115
|
-
.accessibilityLabel(captionsEnabled ? "Captions on" : "Captions off")
|
|
116
|
-
.accessibilityHint("Toggles closed captions")
|
|
117
147
|
```
|
|
@@ -1,141 +1,205 @@
|
|
|
1
1
|
# App Store Accessibility Nutrition Labels
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
3
|
+
Back to [SKILL.md](../SKILL.md).
|
|
4
|
+
|
|
5
|
+
App Store Connect lets a developer state which accessibility features an app
|
|
6
|
+
supports, and the App Store shows those statements on the product page. A
|
|
7
|
+
person can then judge, before installing, whether the app will work with the
|
|
8
|
+
way they use their device.
|
|
9
|
+
|
|
10
|
+
Apple's help pages (App Store Connect Help, section "Manage app
|
|
11
|
+
accessibility"):
|
|
12
|
+
|
|
13
|
+
- Overview:
|
|
14
|
+
https://developer.apple.com/help/app-store-connect/manage-app-accessibility/overview-of-accessibility-nutrition-labels
|
|
15
|
+
- Managing the labels:
|
|
16
|
+
https://developer.apple.com/help/app-store-connect/manage-app-accessibility/manage-accessibility-nutrition-labels
|
|
17
|
+
|
|
18
|
+
## The nine categories
|
|
19
|
+
|
|
20
|
+
There are nine labels today. Each one below says what a user can expect when
|
|
21
|
+
it is shown, and what the app has to do to earn it.
|
|
22
|
+
|
|
23
|
+
1. **VoiceOver.** A blind user can find, understand and operate everything.
|
|
24
|
+
Needs: concise labels with values and traits, a sensible reading order,
|
|
25
|
+
descriptions or text equivalents for images and charts, custom controls
|
|
26
|
+
that behave like real ones.
|
|
27
|
+
2. **Voice Control.** Everything can be done by speaking. Needs: labels a
|
|
28
|
+
person can pronounce, `accessibilityInputLabels` where the label is
|
|
29
|
+
unwieldy, and custom actions for anything hidden behind a gesture.
|
|
30
|
+
3. **Larger Text.** Text can grow to 200% or more where the platform supports
|
|
31
|
+
it. Needs: Dynamic Type, or an in-app text size setting that does the same
|
|
32
|
+
job, without clipping or overlapping.
|
|
33
|
+
4. **Dark Interface.** The screens used for common tasks can stay dark. Needs:
|
|
34
|
+
support for system Dark Mode or an equivalent in-app theme, and no white
|
|
35
|
+
flashes along the way.
|
|
36
|
+
5. **Differentiate Without Color Alone.** No meaning is carried by color on
|
|
37
|
+
its own. Needs: a second cue such as a word, shape, icon, pattern or
|
|
38
|
+
position.
|
|
39
|
+
6. **Sufficient Contrast.** Text, icons, controls and state markers are easy to
|
|
40
|
+
tell from their background. Needs: semantic colors, high-contrast variants,
|
|
41
|
+
handling for Reduce Transparency, checks in both light and dark
|
|
42
|
+
appearances.
|
|
43
|
+
7. **Reduced Motion.** Motion that can cause discomfort can be switched off.
|
|
44
|
+
Needs: the Reduce Motion setting respected, with parallax, spinning,
|
|
45
|
+
scaling, depth effects and continuous animation replaced by fades or still
|
|
46
|
+
frames.
|
|
47
|
+
8. **Captions.** Speech and meaningful sounds in video and audio are available
|
|
48
|
+
as text. Needs: captions, SDH, subtitles or transcripts, and respect for the
|
|
49
|
+
caption preferences set in the system.
|
|
50
|
+
9. **Audio Descriptions.** What happens on screen in time-based media is also
|
|
51
|
+
narrated. Needs: an audio-description track, or narration that does the
|
|
52
|
+
same job, for videos, cut scenes and cues that are only visual.
|
|
53
|
+
|
|
54
|
+
Facts about where the labels appear:
|
|
55
|
+
|
|
56
|
+
- Devices running iOS 26, iPadOS 26, macOS 26, tvOS 26, visionOS 26 and
|
|
57
|
+
watchOS 26, or anything newer, display them.
|
|
58
|
+
- App Store Connect only asks about labels that apply to the device type in
|
|
59
|
+
question.
|
|
60
|
+
|
|
61
|
+
Watch the names. Older drafts and the Settings app use different words:
|
|
62
|
+
|
|
63
|
+
| Say this (label) | Not this |
|
|
64
|
+
|---|---|
|
|
65
|
+
| Captions | Closed Captions / SDH |
|
|
66
|
+
| Sufficient Contrast | Increase Contrast |
|
|
67
|
+
| Reduced Motion | Reduce Motion (that is the setting, not the label) |
|
|
68
|
+
|
|
69
|
+
## Rules for claiming a label
|
|
70
|
+
|
|
71
|
+
- A label is claimed only if people can get through **every** common task in
|
|
72
|
+
the app with that feature.
|
|
73
|
+
- Write the common tasks down per device type, run each one with the feature
|
|
74
|
+
on, and only then fill in App Store Connect.
|
|
75
|
+
- Re-check the answers as the app changes. They describe the product; they
|
|
76
|
+
are not advertising.
|
|
77
|
+
- If a label is intentionally misleading or harmful, App Review may contact
|
|
78
|
+
the developer to have it corrected.
|
|
79
|
+
|
|
80
|
+
Two important features have no label of their own at the moment: Switch
|
|
81
|
+
Control and Full Keyboard Access. They remain part of the job, and their
|
|
82
|
+
guidance lives in [SKILL.md](../SKILL.md) and the
|
|
83
|
+
[code patterns](a11y-patterns.md).
|
|
84
|
+
|
|
85
|
+
## What passes and what fails
|
|
50
86
|
|
|
51
87
|
### VoiceOver
|
|
52
88
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
- Custom controls
|
|
58
|
-
|
|
89
|
+
- Short, meaningful label on every control.
|
|
90
|
+
- No control type or state in the label when VoiceOver already announces it.
|
|
91
|
+
- Charts and informative images come with a description or a text version.
|
|
92
|
+
- Purely decorative imagery is hidden.
|
|
93
|
+
- Custom controls report their role, value and action, and sit in a sensible
|
|
94
|
+
place in the reading order.
|
|
95
|
+
- Changes that matter are announced with the matching accessibility
|
|
96
|
+
notification.
|
|
59
97
|
|
|
60
98
|
### Voice Control
|
|
61
99
|
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
- `accessibilityInputLabels`
|
|
65
|
-
|
|
66
|
-
-
|
|
100
|
+
- Each common task can be finished by voice with nothing else.
|
|
101
|
+
- On-screen wording and the spoken name agree wherever that is practical.
|
|
102
|
+
- Where a label is long, `accessibilityInputLabels` offers a short spoken
|
|
103
|
+
version.
|
|
104
|
+
- Every interactive element shows up under both the names overlay and the
|
|
105
|
+
numbers overlay.
|
|
106
|
+
- Anything that needs a swipe, a long press, a hover or is otherwise hidden
|
|
107
|
+
has a route by speech alone, normally a custom accessibility action.
|
|
67
108
|
|
|
68
109
|
### Larger Text
|
|
69
110
|
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
111
|
+
- Where the platform supports this label, text reaches 200% of its default
|
|
112
|
+
size or more.
|
|
113
|
+
- Core workflows show no clipped, colliding or badly cut-off text.
|
|
114
|
+
- At accessibility sizes, layouts reflow, commonly from side-by-side to
|
|
115
|
+
stacked.
|
|
116
|
+
- Icons and images that work like text either scale with it or have an
|
|
117
|
+
equivalent people can perceive.
|
|
74
118
|
|
|
75
119
|
### Dark Interface
|
|
76
120
|
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
-
|
|
121
|
+
- With dark appearance chosen in the system or in the app, common-task
|
|
122
|
+
screens remain dark.
|
|
123
|
+
- No bright splash while loading, no light interstitials, no white modal
|
|
124
|
+
sheets.
|
|
125
|
+
- Try the dark theme again with the contrast settings switched on.
|
|
80
126
|
|
|
81
127
|
### Differentiate Without Color Alone
|
|
82
128
|
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
-
|
|
129
|
+
- Chart series, selection, validation, status and game or team state all
|
|
130
|
+
have a cue besides color.
|
|
131
|
+
- That cue can be a word, a symbol, a shape, an ordering, a pattern or a
|
|
132
|
+
direct label.
|
|
133
|
+
- Run the important flows with a grayscale or color filter on; anything that
|
|
134
|
+
becomes ambiguous depends on color.
|
|
86
135
|
|
|
87
136
|
### Sufficient Contrast
|
|
88
137
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
|
|
138
|
+
- Body text usually needs a ratio of at least 4.5:1 with its background.
|
|
139
|
+
- Custom controls and non-text indicators of state usually need at least 3:1.
|
|
140
|
+
- Check the combinations: light and dark appearance, each with Increase
|
|
141
|
+
Contrast, Bold Text and Reduce Transparency.
|
|
142
|
+
- When semantic system colors cannot cover a case, custom colors get their own
|
|
143
|
+
high-contrast variants.
|
|
93
144
|
|
|
94
145
|
### Reduced Motion
|
|
95
146
|
|
|
96
|
-
-
|
|
97
|
-
|
|
98
|
-
|
|
147
|
+
- Under Reduce Motion, turn off or replace depth simulation, vortex and
|
|
148
|
+
spinning effects, scaling, parallax, and motion along several axes or at
|
|
149
|
+
several speeds.
|
|
150
|
+
- Anything that keeps moving by itself, such as an auto-advancing carousel,
|
|
151
|
+
either stops or gives the user a control to stop it.
|
|
152
|
+
- The replacement still communicates the same thing: a fade, a highlight or
|
|
153
|
+
an immediate change.
|
|
99
154
|
|
|
100
155
|
### Captions
|
|
101
156
|
|
|
102
|
-
-
|
|
103
|
-
- Captions
|
|
104
|
-
|
|
105
|
-
-
|
|
157
|
+
- Dialogue in video, and sound effects needed to follow it, are captioned.
|
|
158
|
+
- Captions keep time with the audio, are easy to read and name the speaker
|
|
159
|
+
when that is not obvious.
|
|
160
|
+
- Where synced captions do not fit, audio-only dialogue comes with a
|
|
161
|
+
transcript.
|
|
162
|
+
- In AVFoundation the tracks carry `.transcribesSpokenDialogForAccessibility`
|
|
163
|
+
and `.describesMusicAndSoundForAccessibility`
|
|
164
|
+
(details in [media accessibility](media-accessibility.md)).
|
|
106
165
|
|
|
107
166
|
### Audio Descriptions
|
|
108
167
|
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
-
|
|
168
|
+
- The narration covers on-screen text, scene changes, instructions, story
|
|
169
|
+
beats that are only visible, and any other important visual cue.
|
|
170
|
+
- It is placed in natural gaps and never talks over dialogue people need.
|
|
171
|
+
- In AVFoundation the description tracks carry
|
|
172
|
+
`.describesVideoForAccessibility`.
|
|
112
173
|
|
|
113
|
-
## SwiftUI
|
|
174
|
+
## Auditing a SwiftUI screen
|
|
114
175
|
|
|
115
176
|
```swift
|
|
116
|
-
struct
|
|
117
|
-
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
|
177
|
+
struct RecipeHeroView: View {
|
|
118
178
|
@Environment(\.dynamicTypeSize) private var typeSize
|
|
179
|
+
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
|
180
|
+
@State private var isSaved = false
|
|
181
|
+
let recipe: Recipe
|
|
119
182
|
|
|
120
183
|
var body: some View {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.
|
|
184
|
+
let stack = typeSize.isAccessibilitySize
|
|
185
|
+
? AnyLayout(VStackLayout(alignment: .leading))
|
|
186
|
+
: AnyLayout(HStackLayout(alignment: .top))
|
|
187
|
+
|
|
188
|
+
stack {
|
|
189
|
+
Image(recipe.photoName)
|
|
190
|
+
.resizable()
|
|
191
|
+
.scaledToFit()
|
|
192
|
+
.accessibilityLabel(recipe.photoDescription) // VoiceOver
|
|
193
|
+
Text(recipe.title)
|
|
194
|
+
.font(.title) // Larger Text
|
|
195
|
+
Button(isSaved ? "Saved" : "Save recipe") { isSaved.toggle() }
|
|
196
|
+
.accessibilityHint("Adds this recipe to your cookbook")
|
|
130
197
|
}
|
|
131
|
-
.
|
|
198
|
+
.scaleEffect(isSaved ? 1.02 : 1)
|
|
199
|
+
.animation(reduceMotion ? nil : .spring(), value: isSaved) // Reduced Motion
|
|
132
200
|
}
|
|
133
201
|
}
|
|
134
202
|
```
|
|
135
203
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Switch Control and Full Keyboard Access remain important app accessibility
|
|
139
|
-
requirements, but they are not current App Store Accessibility Nutrition Label
|
|
140
|
-
categories. Keep their implementation guidance in `SKILL.md` and
|
|
141
|
-
`references/a11y-patterns.md`.
|
|
204
|
+
Each commented line maps to one label's pass criteria, and the layout switch
|
|
205
|
+
covers the "reflows at accessibility sizes" check.
|