@mmerterden/multi-agent-pipeline 20.6.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 +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- 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/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- 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/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- 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/ci-cd-pipelines/SKILL.md +1 -0
- 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/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- 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/council/SKILL.md +1 -0
- 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/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- 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/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- 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/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- 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-coding-standard/SKILL.md +1 -0
- 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-module-structure/SKILL.md +1 -0
- 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-security/SKILL.md +2 -0
- 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/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- 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/nextjs-app-router/SKILL.md +1 -0
- 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/play-store-review/SKILL.md +2 -0
- 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/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- 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/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- 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/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- 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/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- 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/typescript-patterns/SKILL.md +1 -0
- 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/vue-composition/SKILL.md +1 -0
- 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/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- 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,97 +1,115 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Forms
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Form guidance for the `swiftui-layout-components` skill.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## When to use Form
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Settings, grouped inputs and action rows belong in a `Form`. It gives
|
|
8
|
+
consistent layout, spacing and accessibility without hand tuning.
|
|
8
9
|
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
-
|
|
10
|
+
- Add a `NavigationStack` around it only when it is presented in a sheet or
|
|
11
|
+
stands alone with no navigation context.
|
|
12
|
+
- For design-system colors, hide the default background with
|
|
13
|
+
`.scrollContentBackground(.hidden)` and supply your own.
|
|
14
|
+
- `.formStyle(.grouped)` where the grouped look fits.
|
|
15
|
+
- `@FocusState` for moving between fields.
|
|
14
16
|
|
|
15
|
-
##
|
|
17
|
+
## Settings form
|
|
16
18
|
|
|
17
19
|
```swift
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
struct NotificationSettings: View {
|
|
21
|
+
@AppStorage("alerts.digest") private var dailyDigest = true
|
|
22
|
+
@AppStorage("alerts.sound") private var playSound = false
|
|
23
|
+
|
|
24
|
+
var body: some View {
|
|
25
|
+
Form {
|
|
26
|
+
Section("Alerts") {
|
|
27
|
+
Toggle("Daily Digest", isOn: $dailyDigest)
|
|
28
|
+
Toggle("Play Sound", isOn: $playSound)
|
|
29
|
+
}
|
|
30
|
+
.listRowBackground(Color.cardSurface)
|
|
31
|
+
|
|
32
|
+
Section {
|
|
33
|
+
Button { openSystemSettings() } label: {
|
|
34
|
+
Label("System Notification Settings", systemImage: "gear")
|
|
35
|
+
}
|
|
36
|
+
.buttonStyle(.plain)
|
|
37
|
+
}
|
|
38
|
+
.listRowBackground(Color.cardSurface)
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
.listRowBackground(theme.primaryBackgroundColor)
|
|
35
|
-
}
|
|
36
|
-
.navigationTitle("Settings")
|
|
37
|
-
.navigationBarTitleDisplayMode(.inline)
|
|
38
|
-
.scrollContentBackground(.hidden)
|
|
39
|
-
.background(theme.secondaryBackgroundColor)
|
|
40
|
+
.navigationTitle("Notifications")
|
|
41
|
+
.navigationBarTitleDisplayMode(.inline)
|
|
42
|
+
.scrollContentBackground(.hidden)
|
|
43
|
+
.background(Color.screenBackground)
|
|
40
44
|
}
|
|
41
|
-
|
|
45
|
+
|
|
46
|
+
private func openSystemSettings() {}
|
|
42
47
|
}
|
|
43
48
|
```
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
`Color.cardSurface` and `Color.screenBackground` stand for your design-system
|
|
51
|
+
colors.
|
|
52
|
+
|
|
53
|
+
## Modal form with validation
|
|
46
54
|
|
|
47
55
|
```swift
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
struct AddFeedSheet: View {
|
|
57
|
+
@Environment(\.dismiss) private var dismiss
|
|
58
|
+
@State private var address = ""
|
|
59
|
+
@FocusState private var addressFocused: Bool
|
|
60
|
+
|
|
61
|
+
private var isValid: Bool {
|
|
62
|
+
guard let url = URL(string: address) else { return false }
|
|
63
|
+
return url.scheme == "https" && url.host() != nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var body: some View {
|
|
67
|
+
NavigationStack {
|
|
68
|
+
Form {
|
|
69
|
+
Section("Feed Address") {
|
|
70
|
+
TextField("https://", text: $address)
|
|
71
|
+
.keyboardType(.URL)
|
|
72
|
+
.textInputAutocapitalization(.never)
|
|
73
|
+
.autocorrectionDisabled()
|
|
74
|
+
.focused($addressFocused)
|
|
75
|
+
}
|
|
76
|
+
Section {
|
|
77
|
+
Button("Add Feed") {
|
|
78
|
+
guard isValid else { return }
|
|
79
|
+
subscribe()
|
|
80
|
+
dismiss()
|
|
81
|
+
}
|
|
82
|
+
.disabled(!isValid)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
.scrollDismissesKeyboard(.immediately)
|
|
86
|
+
.navigationTitle("New Feed")
|
|
87
|
+
.toolbar {
|
|
88
|
+
ToolbarItem(placement: .cancellationAction) {
|
|
89
|
+
Button("Cancel") { dismiss() }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
.onAppear { addressFocused = true }
|
|
70
93
|
}
|
|
71
|
-
.disabled(!isValid)
|
|
72
|
-
.listRowBackground(theme.primaryBackgroundColor)
|
|
73
|
-
}
|
|
74
|
-
.formStyle(.grouped)
|
|
75
|
-
.navigationTitle("Add Server")
|
|
76
|
-
.navigationBarTitleDisplayMode(.inline)
|
|
77
|
-
.scrollContentBackground(.hidden)
|
|
78
|
-
.background(theme.secondaryBackgroundColor)
|
|
79
|
-
.scrollDismissesKeyboard(.immediately)
|
|
80
|
-
.toolbar { CancelToolbarItem() }
|
|
81
|
-
.onAppear { isServerFieldFocused = true }
|
|
82
94
|
}
|
|
83
|
-
|
|
95
|
+
|
|
96
|
+
private func subscribe() {}
|
|
84
97
|
}
|
|
85
98
|
```
|
|
86
99
|
|
|
87
|
-
|
|
100
|
+
The submit button is disabled until the input is valid and checks again when
|
|
101
|
+
tapped; the field is focused as soon as the sheet appears.
|
|
102
|
+
|
|
103
|
+
## Design choices
|
|
88
104
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
|
|
105
|
+
- A `Form` beats a custom stack for settings and data entry.
|
|
106
|
+
- Rows with buttons stay fully tappable with `.contentShape(Rectangle())` and
|
|
107
|
+
`.buttonStyle(.plain)`.
|
|
108
|
+
- `.listRowBackground(_:)` matches rows to the theme.
|
|
92
109
|
|
|
93
110
|
## Pitfalls
|
|
94
111
|
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
-
|
|
112
|
+
- Heavy custom layouts inside a `Form` fight its spacing; for very custom
|
|
113
|
+
screens use `ScrollView` with a `VStack`.
|
|
114
|
+
- Choose one background approach: the default form styling or your own
|
|
115
|
+
colors, not a mix of both.
|
|
@@ -1,230 +1,165 @@
|
|
|
1
1
|
# Grids
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- Intent
|
|
5
|
-
- Choosing the right grid type
|
|
6
|
-
- Column strategies
|
|
7
|
-
- Cell sizing and aspect ratio
|
|
8
|
-
- Example: adaptive icon grid
|
|
9
|
-
- Example: fixed 3-column media grid
|
|
10
|
-
- Example: sectioned grid
|
|
11
|
-
- Selection and interaction patterns
|
|
12
|
-
- Performance guardrails
|
|
13
|
-
- Accessibility and polish
|
|
14
|
-
- Pitfalls
|
|
3
|
+
Grid guidance for the `swiftui-layout-components` skill.
|
|
15
4
|
|
|
16
|
-
##
|
|
5
|
+
## When a grid is the right shape
|
|
17
6
|
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
Reach for a grid when items are visual and a one-per-row list would waste
|
|
8
|
+
width or slow scanning: icon pickers, photo and video galleries, template
|
|
9
|
+
choosers, settings tiles, dashboards of cards. On iOS the everyday choice is a
|
|
10
|
+
`LazyVGrid` in a vertical `ScrollView`. `Grid` is for a handful of items that
|
|
11
|
+
do not scroll, or when you need to compose rows explicitly.
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
## Picking the grid type
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
Default to `LazyVGrid` for vertically scrolling collections on iOS. Reach for
|
|
30
|
-
`Grid` when content is small and non-scrollable, or when you need explicit row
|
|
31
|
-
composition rather than a large lazy container.
|
|
32
|
-
|
|
33
|
-
## Choosing the right grid type
|
|
34
|
-
|
|
35
|
-
### `LazyVGrid`
|
|
36
|
-
|
|
37
|
-
Use for the common iPhone/iPad case: many items, vertical scrolling, and a
|
|
38
|
-
column definition that should adapt to width.
|
|
39
|
-
|
|
40
|
-
### `LazyHGrid`
|
|
41
|
-
|
|
42
|
-
Use when horizontal scrolling is the dominant interaction and rows are easier to
|
|
43
|
-
define than columns.
|
|
44
|
-
|
|
45
|
-
### `Grid`
|
|
46
|
-
|
|
47
|
-
Use when:
|
|
48
|
-
|
|
49
|
-
- the item count is small
|
|
50
|
-
- the content is mostly static
|
|
51
|
-
- row/column relationships matter more than lazy loading
|
|
52
|
-
- you need `GridRow` composition instead of a repeated collection layout
|
|
53
|
-
|
|
54
|
-
For large scrolling datasets, `LazyVGrid` is usually the safer default.
|
|
15
|
+
| Type | Pick it when |
|
|
16
|
+
|------|--------------|
|
|
17
|
+
| `LazyVGrid` | Many items, vertical scrolling, column count should follow width. The usual iPhone and iPad case, and the safe default for big data sets |
|
|
18
|
+
| `LazyHGrid` | Horizontal scrolling is the main motion and rows are easier to describe than columns |
|
|
19
|
+
| `Grid` + `GridRow` | Few, mostly static items where alignment across rows and columns matters more than laziness |
|
|
55
20
|
|
|
56
21
|
## Column strategies
|
|
57
22
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
width.
|
|
62
|
-
|
|
63
|
-
```swift
|
|
64
|
-
let columns = [GridItem(.adaptive(minimum: 120, maximum: 240))]
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
This is the best default for icon pickers, template choosers, and photo grids
|
|
68
|
-
that should scale naturally across iPhone and iPad sizes.
|
|
23
|
+
**Adaptive.** `GridItem(.adaptive(minimum: 110, maximum: 220))` fits as many
|
|
24
|
+
columns as the width allows. Start here for photo grids, template choosers and
|
|
25
|
+
icon pickers.
|
|
69
26
|
|
|
70
|
-
|
|
27
|
+
**Flexible.** Two or three `.flexible(minimum: 100)` items give a steady
|
|
28
|
+
two-up or three-up rhythm regardless of device.
|
|
71
29
|
|
|
72
|
-
|
|
30
|
+
**Fixed.** `.fixed(width)` only when an exact width is required. It copes
|
|
31
|
+
poorly with different screen sizes and with Dynamic Type.
|
|
73
32
|
|
|
74
|
-
|
|
75
|
-
let columns = [
|
|
76
|
-
GridItem(.flexible(minimum: 100)),
|
|
77
|
-
GridItem(.flexible(minimum: 100)),
|
|
78
|
-
GridItem(.flexible(minimum: 100)),
|
|
79
|
-
]
|
|
80
|
-
```
|
|
33
|
+
## Sizing cells
|
|
81
34
|
|
|
82
|
-
|
|
35
|
+
A cell decides its own shape; it never asks the parent how big it is.
|
|
83
36
|
|
|
84
|
-
|
|
37
|
+
- Square tiles come from `.aspectRatio(1, contentMode: .fit)`.
|
|
38
|
+
- `.frame(maxWidth: .infinity)` to fill the column.
|
|
39
|
+
- Padding inside the cell instead of arithmetic on geometry.
|
|
85
40
|
|
|
86
|
-
|
|
87
|
-
|
|
41
|
+
Avoid `GeometryReader` in lazy containers: it breaks lazy layout and adds
|
|
42
|
+
measurement passes. If a cell truly must react to its size, use
|
|
43
|
+
`.onGeometryChange(for:of:action:)`. Apple lists it for iOS 16.0+, macOS
|
|
44
|
+
13.0+, tvOS 16.0+, watchOS 9.0+ and visionOS 1.0+ (back-deployed, so compile
|
|
45
|
+
with the Xcode 16 SDK or newer).
|
|
88
46
|
|
|
89
|
-
##
|
|
90
|
-
|
|
91
|
-
Grid cells should usually define their own shape without reading parent
|
|
92
|
-
geometry.
|
|
93
|
-
|
|
94
|
-
Preferred sizing tools:
|
|
95
|
-
|
|
96
|
-
- `.aspectRatio(1, contentMode: .fit)` for square thumbnails
|
|
97
|
-
- `.frame(maxWidth: .infinity)` when content should fill the available column
|
|
98
|
-
- internal padding instead of outer geometry math
|
|
99
|
-
|
|
100
|
-
Avoid `GeometryReader` inside lazy containers. It defeats lazy layout and adds
|
|
101
|
-
extra measurement work.
|
|
102
|
-
|
|
103
|
-
## Example: adaptive icon grid
|
|
47
|
+
## Adaptive picker with selection
|
|
104
48
|
|
|
105
49
|
```swift
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
50
|
+
struct WallpaperPicker: View {
|
|
51
|
+
let wallpapers: [Wallpaper]
|
|
52
|
+
@Binding var chosen: Wallpaper.ID?
|
|
53
|
+
|
|
54
|
+
var body: some View {
|
|
55
|
+
ScrollView {
|
|
56
|
+
LazyVGrid(columns: [GridItem(.adaptive(minimum: 104, maximum: 180))]) {
|
|
57
|
+
ForEach(wallpapers) { paper in
|
|
58
|
+
Button { chosen = paper.id } label: {
|
|
59
|
+
ZStack(alignment: .bottomTrailing) {
|
|
60
|
+
Image(paper.assetName)
|
|
61
|
+
.resizable()
|
|
62
|
+
.aspectRatio(1, contentMode: .fit)
|
|
63
|
+
.clipShape(.rect(cornerRadius: 10))
|
|
64
|
+
if chosen == paper.id {
|
|
65
|
+
Image(systemName: "checkmark.circle.fill")
|
|
66
|
+
.foregroundStyle(.white, .tint)
|
|
67
|
+
.padding(6)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
.buttonStyle(.plain)
|
|
72
|
+
.contentShape(Rectangle())
|
|
73
|
+
.accessibilityLabel(paper.title)
|
|
74
|
+
.accessibilityAddTraits(chosen == paper.id ? .isSelected : [])
|
|
123
75
|
}
|
|
124
76
|
}
|
|
77
|
+
.padding()
|
|
125
78
|
}
|
|
126
|
-
.buttonStyle(.plain)
|
|
127
|
-
.contentShape(Rectangle())
|
|
128
79
|
}
|
|
129
80
|
}
|
|
130
81
|
```
|
|
131
82
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- adaptive columns scale across width classes
|
|
135
|
-
- square-ish cells come from image aspect ratio, not geometry reads
|
|
136
|
-
- the whole tile remains tappable
|
|
83
|
+
Adaptive columns follow the size class, the image's aspect ratio (not geometry)
|
|
84
|
+
makes the tile square, and the whole tile is the hit area.
|
|
137
85
|
|
|
138
|
-
##
|
|
86
|
+
## Three-up media gallery
|
|
139
87
|
|
|
140
88
|
```swift
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
89
|
+
struct ClipGallery: View {
|
|
90
|
+
let clips: [Clip]
|
|
91
|
+
private let columns = [GridItem](
|
|
92
|
+
repeating: GridItem(.flexible(minimum: 96), spacing: 3),
|
|
93
|
+
count: 3
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
var body: some View {
|
|
97
|
+
ScrollView {
|
|
98
|
+
LazyVGrid(columns: columns, spacing: 3) {
|
|
99
|
+
ForEach(clips) { clip in
|
|
100
|
+
ClipThumbnail(clip: clip)
|
|
101
|
+
.aspectRatio(1, contentMode: .fill)
|
|
102
|
+
.clipShape(.rect(cornerRadius: 4))
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
153
106
|
}
|
|
154
107
|
}
|
|
155
108
|
```
|
|
156
109
|
|
|
157
|
-
Use this when
|
|
158
|
-
an adaptive count.
|
|
159
|
-
|
|
160
|
-
## Example: sectioned grid
|
|
110
|
+
Use this when every row should show exactly three thumbnails.
|
|
161
111
|
|
|
162
|
-
|
|
112
|
+
## Sections in a grid
|
|
163
113
|
|
|
164
114
|
```swift
|
|
165
|
-
LazyVGrid(columns: [GridItem(.adaptive(minimum:
|
|
166
|
-
ForEach(
|
|
115
|
+
LazyVGrid(columns: [GridItem(.adaptive(minimum: 120))]) {
|
|
116
|
+
ForEach(shelves) { shelf in
|
|
167
117
|
Section {
|
|
168
|
-
ForEach(
|
|
169
|
-
Tile(item: item)
|
|
170
|
-
}
|
|
118
|
+
ForEach(shelf.books) { BookCover(book: $0) }
|
|
171
119
|
} header: {
|
|
172
|
-
Text(
|
|
120
|
+
Text(shelf.name)
|
|
173
121
|
.font(.headline)
|
|
174
122
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
175
|
-
.padding(.top)
|
|
176
123
|
}
|
|
177
124
|
}
|
|
178
125
|
}
|
|
179
126
|
```
|
|
180
127
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
## Selection and interaction patterns
|
|
185
|
-
|
|
186
|
-
Grid interactions should stay obvious and forgiving.
|
|
187
|
-
|
|
188
|
-
Useful defaults:
|
|
189
|
-
|
|
190
|
-
- make the entire cell tappable with `.contentShape(Rectangle())`
|
|
191
|
-
- show selection state in one consistent corner or border treatment
|
|
192
|
-
- keep hover/focus/pressed states subtle but visible
|
|
193
|
-
- avoid stacking too many overlays on every item
|
|
194
|
-
|
|
195
|
-
For multi-select grids, prefer clear selection affordances instead of hidden
|
|
196
|
-
state changes triggered only by long press.
|
|
128
|
+
Grouping works well for categories or a recents row. Keep headers small; big
|
|
129
|
+
headers slow down scanning.
|
|
197
130
|
|
|
198
|
-
##
|
|
131
|
+
## Selection and interaction
|
|
199
132
|
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
- Precompute grouped or filtered collections before rendering.
|
|
133
|
+
- The whole cell is the tap target (`.contentShape(Rectangle())`).
|
|
134
|
+
- Mark selection the same way everywhere: one corner badge or one border style.
|
|
135
|
+
- Pressed, hover and focus states should be quiet but visible.
|
|
136
|
+
- Few overlays per cell.
|
|
137
|
+
- Multi-select needs a visible affordance; do not hide it behind long press.
|
|
206
138
|
|
|
207
|
-
|
|
208
|
-
state invalidation before changing the grid structure itself.
|
|
139
|
+
## Performance
|
|
209
140
|
|
|
210
|
-
|
|
141
|
+
- `LazyVGrid` for large collections.
|
|
142
|
+
- Downsample big images before display.
|
|
143
|
+
- No expensive formatting or filtering inside cell bodies; precompute grouped
|
|
144
|
+
or filtered arrays.
|
|
145
|
+
- Stable identity for every item.
|
|
146
|
+
- Janky scrolling? Measure first: image decoding, overlays on each cell and
|
|
147
|
+
state that invalidates too often are the usual causes, and fixing them is
|
|
148
|
+
cheaper than rebuilding the grid.
|
|
211
149
|
|
|
212
|
-
|
|
213
|
-
- Test with Dynamic Type even if cells are primarily visual.
|
|
214
|
-
- Ensure VoiceOver labels describe the item and selection state.
|
|
215
|
-
- Use meaningful focus order on iPad and keyboard-driven flows.
|
|
216
|
-
- Avoid tiny hit targets even when cells are visually dense.
|
|
150
|
+
## Accessibility
|
|
217
151
|
|
|
218
|
-
|
|
219
|
-
|
|
152
|
+
- Group clearly and space consistently.
|
|
153
|
+
- Try the largest Dynamic Type sizes, even for image-heavy cells.
|
|
154
|
+
- VoiceOver labels name the item and say whether it is selected.
|
|
155
|
+
- On iPad and with a keyboard, focus should move in a sensible order.
|
|
156
|
+
- Keep hit targets comfortably large.
|
|
220
157
|
|
|
221
158
|
## Pitfalls
|
|
222
159
|
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
|
|
229
|
-
defeats lazy loading. Use `.aspectRatio` for sizing, or `.onGeometryChange`
|
|
230
|
-
(iOS 18+) if you need to read dimensions.
|
|
160
|
+
- A heavy overlay stack on every cell.
|
|
161
|
+
- Grids nested inside grids without a reason.
|
|
162
|
+
- Filtering inline in `ForEach`.
|
|
163
|
+
- Fixed columns where adaptive ones fit the goal.
|
|
164
|
+
- `GeometryReader` in `LazyVGrid`, `LazyHGrid`, `LazyVStack` or `LazyHStack`;
|
|
165
|
+
use `.aspectRatio`, or `.onGeometryChange` (iOS 16.0+) when a size must be read.
|