@devo-bmad-custom/agent-orchestration 1.0.2 → 1.0.4
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/lib/installer.js +33 -0
- package/package.json +1 -1
- package/src/.agents/skills/audit-website/README.md +20 -20
- package/src/.agents/skills/audit-website/SKILL.md +470 -470
- package/src/.agents/skills/audit-website/agents/openai.yaml +6 -6
- package/src/.agents/skills/audit-website/assets/icon-small.svg +41 -41
- package/src/.agents/skills/audit-website/references/OUTPUT-FORMAT.md +250 -250
- package/src/.agents/skills/clean-code-standards/SKILL.md +104 -104
- package/src/.agents/skills/excalidraw-dark-standard/SKILL.md +281 -281
- package/src/.agents/skills/frontend-responsive-design-standards/SKILL.md +434 -434
- package/src/.agents/skills/java-fundamentals/SKILL.md +116 -116
- package/src/.agents/skills/java-performance/SKILL.md +119 -119
- package/src/.agents/skills/next-best-practices/SKILL.md +153 -153
- package/src/.agents/skills/next-best-practices/async-patterns.md +87 -87
- package/src/.agents/skills/next-best-practices/bundling.md +180 -180
- package/src/.agents/skills/next-best-practices/data-patterns.md +297 -297
- package/src/.agents/skills/next-best-practices/debug-tricks.md +105 -105
- package/src/.agents/skills/next-best-practices/directives.md +73 -73
- package/src/.agents/skills/next-best-practices/error-handling.md +227 -227
- package/src/.agents/skills/next-best-practices/file-conventions.md +140 -140
- package/src/.agents/skills/next-best-practices/font.md +245 -245
- package/src/.agents/skills/next-best-practices/functions.md +108 -108
- package/src/.agents/skills/next-best-practices/hydration-error.md +91 -91
- package/src/.agents/skills/next-best-practices/image.md +173 -173
- package/src/.agents/skills/next-best-practices/metadata.md +301 -301
- package/src/.agents/skills/next-best-practices/parallel-routes.md +287 -287
- package/src/.agents/skills/next-best-practices/route-handlers.md +146 -146
- package/src/.agents/skills/next-best-practices/rsc-boundaries.md +159 -159
- package/src/.agents/skills/next-best-practices/runtime-selection.md +39 -39
- package/src/.agents/skills/next-best-practices/scripts.md +141 -141
- package/src/.agents/skills/next-best-practices/self-hosting.md +371 -371
- package/src/.agents/skills/next-best-practices/suspense-boundaries.md +67 -67
- package/src/.agents/skills/nextjs-app-router-patterns/SKILL.md +537 -537
- package/src/.agents/skills/postgresql-optimization/SKILL.md +404 -404
- package/src/.agents/skills/python-backend/SKILL.md +153 -153
- package/src/.agents/skills/python-fundamentals/SKILL.md +234 -234
- package/src/.agents/skills/python-performance/SKILL.md +404 -404
- package/src/.agents/skills/react-expert/SKILL.md +335 -335
- package/src/.agents/skills/redis-best-practices/SKILL.md +438 -438
- package/src/.agents/skills/security-best-practices/SKILL.md +288 -288
- package/src/.agents/skills/security-review/LICENSE +22 -22
- package/src/.agents/skills/security-review/SKILL.md +312 -312
- package/src/.agents/skills/security-review/infrastructure/docker.md +432 -432
- package/src/.agents/skills/security-review/languages/javascript.md +388 -388
- package/src/.agents/skills/security-review/languages/python.md +363 -363
- package/src/.agents/skills/security-review/references/api-security.md +519 -519
- package/src/.agents/skills/security-review/references/authentication.md +353 -353
- package/src/.agents/skills/security-review/references/authorization.md +372 -372
- package/src/.agents/skills/security-review/references/business-logic.md +443 -443
- package/src/.agents/skills/security-review/references/cryptography.md +329 -329
- package/src/.agents/skills/security-review/references/csrf.md +398 -398
- package/src/.agents/skills/security-review/references/data-protection.md +378 -378
- package/src/.agents/skills/security-review/references/deserialization.md +410 -410
- package/src/.agents/skills/security-review/references/error-handling.md +436 -436
- package/src/.agents/skills/security-review/references/file-security.md +457 -457
- package/src/.agents/skills/security-review/references/injection.md +259 -259
- package/src/.agents/skills/security-review/references/logging.md +433 -433
- package/src/.agents/skills/security-review/references/misconfiguration.md +435 -435
- package/src/.agents/skills/security-review/references/modern-threats.md +475 -475
- package/src/.agents/skills/security-review/references/ssrf.md +415 -415
- package/src/.agents/skills/security-review/references/supply-chain.md +405 -405
- package/src/.agents/skills/security-review/references/xss.md +336 -336
- package/src/.agents/skills/subagent-driven-development/SKILL.md +275 -275
- package/src/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -26
- package/src/.agents/skills/subagent-driven-development/implementer-prompt.md +113 -113
- package/src/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -61
- package/src/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/src/.agents/skills/systematic-debugging/SKILL.md +296 -296
- package/src/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/src/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/src/.agents/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/src/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/src/.agents/skills/systematic-debugging/test-academic.md +14 -14
- package/src/.agents/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/src/.agents/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/src/.agents/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/src/.agents/skills/typescript-best-practices/SKILL.md +373 -373
- package/src/.agents/skills/ui-ux-pro-custom/SKILL.md +348 -348
- package/src/.agents/skills/ui-ux-pro-custom/data/charts.csv +26 -26
- package/src/.agents/skills/ui-ux-pro-custom/data/colors.csv +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/icons.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/SKILL.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/accessibility.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/animation.md +466 -466
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/composition-locals.md +231 -231
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/deprecated-patterns.md +323 -323
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/lists-scrolling.md +400 -400
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/modifiers.md +331 -331
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/navigation.md +416 -416
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/performance.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/side-effects.md +516 -516
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/foundation-source.md +13327 -13327
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/material3-source.md +19097 -19097
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/navigation-source.md +2947 -2947
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/runtime-source.md +11316 -11316
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/ui-source.md +7896 -7896
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/state-management.md +377 -377
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/styles-experimental.md +470 -470
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/theming-material3.md +349 -349
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/view-composition.md +595 -595
- package/src/.agents/skills/ui-ux-pro-custom/data/landing.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/data/mobile-ui-layout.md +654 -654
- package/src/.agents/skills/ui-ux-pro-custom/data/products.csv +96 -96
- package/src/.agents/skills/ui-ux-pro-custom/data/react-performance.csv +45 -45
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/astro.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/flutter.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/html-tailwind.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/jetpack-compose.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nextjs.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxt-ui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxtjs.csv +59 -59
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react-native.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/shadcn.csv +61 -61
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/svelte.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/swiftui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/vue.csv +50 -50
- package/src/.agents/skills/ui-ux-pro-custom/data/styles.csv +68 -68
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/SKILL.md +438 -438
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/references/alarmkit-patterns.md +584 -584
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-clips/SKILL.md +436 -436
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/SKILL.md +489 -489
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/references/appintents-advanced.md +1076 -1076
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/SKILL.md +340 -340
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/privacy-manifest.md +90 -90
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/review-checklists.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-conversion.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-optimization.md +344 -344
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/foundation-models.md +508 -508
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/mlx-swift.md +285 -285
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/references/keychain-biometric.md +211 -211
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/SKILL.md +499 -499
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/references/background-task-patterns.md +390 -390
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/SKILL.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/references/callkit-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/SKILL.md +492 -492
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/references/cloudkit-patterns.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/codable-patterns/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/SKILL.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/references/contacts-patterns.md +409 -409
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/references/ble-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/SKILL.md +388 -388
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/references/motion-patterns.md +405 -405
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/SKILL.md +495 -495
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/references/nfc-patterns.md +420 -420
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/SKILL.md +459 -459
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/references/coreml-swift-integration.md +765 -765
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/SKILL.md +422 -422
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/instruments-guide.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/lldb-patterns.md +298 -298
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/device-integrity/SKILL.md +477 -477
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/SKILL.md +460 -460
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/references/energykit-patterns.md +541 -541
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/references/eventkit-patterns.md +326 -326
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/references/healthkit-patterns.md +602 -602
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/references/matter-commissioning.md +455 -455
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/SKILL.md +301 -301
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/references/a11y-patterns.md +140 -140
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/SKILL.md +418 -418
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/formatstyle-locale.md +627 -627
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/string-catalogs.md +462 -462
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/SKILL.md +441 -441
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/background-websocket.md +862 -862
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/lightweight-clients.md +93 -93
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/network-framework.md +563 -563
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/urlsession-patterns.md +1116 -1116
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/app-review-guidelines.md +174 -174
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/cryptokit-advanced.md +296 -296
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/file-storage-patterns.md +354 -354
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/privacy-manifest.md +117 -117
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/references/live-activity-patterns.md +868 -868
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/corelocation-patterns.md +730 -730
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/mapkit-patterns.md +748 -748
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/metrickit-diagnostics/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/SKILL.md +395 -395
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/references/musickit-patterns.md +363 -363
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/SKILL.md +412 -412
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/references/translation-patterns.md +311 -311
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/SKILL.md +398 -398
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/references/wallet-passes.md +254 -254
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/SKILL.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/paperkit-integration.md +376 -376
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/pencilkit-patterns.md +302 -302
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/SKILL.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/references/permissionkit-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/av-playback.md +701 -701
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/camera-capture.md +774 -774
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/image-loading-caching.md +869 -869
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/photospicker-patterns.md +597 -597
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/notification-patterns.md +677 -677
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/rich-notifications.md +745 -745
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/references/realitykit-patterns.md +480 -480
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/references/shareplay-patterns.md +544 -544
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/speech-recognition/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/SKILL.md +478 -478
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/app-review-guidelines.md +58 -58
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/storekit-advanced.md +755 -755
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/SKILL.md +487 -487
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/references/charts-patterns.md +895 -895
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/SKILL.md +408 -408
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/approachable-concurrency.md +80 -80
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swift-6-2-concurrency.md +233 -233
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swiftui-concurrency.md +187 -187
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/synchronization-primitives.md +341 -341
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/references/swift-patterns-extended.md +505 -505
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/references/testing-patterns.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/SKILL.md +334 -334
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/core-data-coexistence.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-advanced.md +975 -975
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-queries.md +675 -675
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/SKILL.md +481 -481
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/animation-advanced.md +804 -804
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/core-animation-bridge.md +553 -553
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/SKILL.md +450 -450
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/references/gesture-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/SKILL.md +336 -336
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/form.md +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/grids.md +69 -69
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/list.md +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/scrollview.md +147 -147
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/SKILL.md +325 -325
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/references/liquid-glass.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/SKILL.md +262 -262
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/deeplinks.md +207 -207
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/navigationstack.md +177 -177
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/sheets.md +169 -169
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/tabview.md +178 -178
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/SKILL.md +381 -381
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/architecture-patterns.md +486 -486
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/deprecated-migration.md +1097 -1097
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/design-polish.md +780 -780
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/platform-and-sharing.md +696 -696
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +46 -46
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +29 -29
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-hangs-in-your-app.md +33 -33
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-improving-swiftui-performance.md +52 -52
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/SKILL.md +428 -428
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/hosting-migration.md +534 -534
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/representable-recipes.md +1133 -1133
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/SKILL.md +494 -494
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/references/tipkit-patterns.md +782 -782
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/SKILL.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/vision-requests.md +736 -736
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/visionkit-scanner.md +738 -738
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/SKILL.md +410 -410
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/references/weatherkit-patterns.md +567 -567
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/SKILL.md +497 -497
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/references/widgetkit-advanced.md +871 -871
- package/src/.agents/skills/ui-ux-pro-custom/data/typography.csv +57 -57
- package/src/.agents/skills/ui-ux-pro-custom/data/ui-reasoning.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/ux-guidelines.csv +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/web-interface.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/scripts/core.py +253 -253
- package/src/.agents/skills/ui-ux-pro-custom/scripts/design_system.py +1067 -1067
- package/src/.agents/skills/ui-ux-pro-custom/scripts/search.py +114 -114
- package/src/.agents/skills/ux-audit/SKILL.md +150 -150
- package/src/.agents/skills/websocket-engineer/SKILL.md +168 -168
- package/src/.agents/skills/websocket-engineer/references/alternatives.md +391 -391
- package/src/.agents/skills/websocket-engineer/references/patterns.md +400 -400
- package/src/.agents/skills/websocket-engineer/references/protocol.md +195 -195
- package/src/.agents/skills/websocket-engineer/references/scaling.md +333 -333
- package/src/.agents/skills/websocket-engineer/references/security.md +474 -474
- package/src/.agents/skills/writing-skills/SKILL.md +655 -655
- package/src/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -1150
- package/src/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/src/.agents/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/src/.agents/skills/writing-skills/persuasion-principles.md +187 -187
- package/src/.agents/skills/writing-skills/render-graphs.js +168 -168
- package/src/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -384
- package/src/.claude/commands/master-orchestrator.md +15 -0
- package/src/_memory/config.yaml +11 -11
- package/src/_memory/master-orchestrator-sidecar/instructions.md +97 -47
- package/src/_memory/skills/nimbalyst-tracking/SKILL.md +103 -103
- package/src/_memory/skills/writing-skills/SKILL.md +655 -655
- package/src/bmb/agents/agent-builder.md +59 -59
- package/src/bmb/agents/module-builder.md +60 -60
- package/src/bmb/agents/workflow-builder.md +61 -61
- package/src/bmb/config.yaml +12 -12
- package/src/bmb/module-help.csv +13 -13
- package/src/bmb/workflows/agent/data/agent-architecture.md +258 -258
- package/src/bmb/workflows/agent/data/agent-compilation.md +185 -185
- package/src/bmb/workflows/agent/data/agent-menu-patterns.md +189 -189
- package/src/bmb/workflows/agent/data/agent-metadata.md +133 -133
- package/src/bmb/workflows/agent/data/agent-validation.md +111 -111
- package/src/bmb/workflows/agent/data/brainstorm-context.md +96 -96
- package/src/bmb/workflows/agent/data/communication-presets.csv +61 -61
- package/src/bmb/workflows/agent/data/critical-actions.md +75 -75
- package/src/bmb/workflows/agent/data/persona-properties.md +252 -252
- package/src/bmb/workflows/agent/data/principles-crafting.md +142 -142
- package/src/bmb/workflows/agent/data/reference/module-examples/architect.md +68 -68
- package/src/bmb/workflows/agent/data/reference/with-sidecar/journal-keeper/journal-keeper-sidecar/entries/yy-mm-dd-entry-template.md +16 -16
- package/src/bmb/workflows/agent/data/understanding-agent-types.md +126 -126
- package/src/bmb/workflows/agent/steps-c/step-01-brainstorm.md +129 -129
- package/src/bmb/workflows/agent/steps-c/step-02-discovery.md +170 -170
- package/src/bmb/workflows/agent/steps-c/step-03-sidecar-metadata.md +309 -309
- package/src/bmb/workflows/agent/steps-c/step-04-persona.md +213 -213
- package/src/bmb/workflows/agent/steps-c/step-05-commands-menu.md +179 -179
- package/src/bmb/workflows/agent/steps-c/step-06-activation.md +278 -278
- package/src/bmb/workflows/agent/steps-c/step-07-build-agent.md +316 -316
- package/src/bmb/workflows/agent/steps-c/step-08-celebrate.md +247 -247
- package/src/bmb/workflows/agent/steps-e/e-01-load-existing.md +221 -221
- package/src/bmb/workflows/agent/steps-e/e-02-discover-edits.md +195 -195
- package/src/bmb/workflows/agent/steps-e/e-04-sidecar-metadata.md +126 -126
- package/src/bmb/workflows/agent/steps-e/e-05-persona.md +135 -135
- package/src/bmb/workflows/agent/steps-e/e-06-commands-menu.md +123 -123
- package/src/bmb/workflows/agent/steps-e/e-07-activation.md +124 -124
- package/src/bmb/workflows/agent/steps-e/e-08-edit-agent.md +197 -197
- package/src/bmb/workflows/agent/steps-e/e-09-celebrate.md +155 -155
- package/src/bmb/workflows/agent/steps-v/v-01-load-review.md +137 -137
- package/src/bmb/workflows/agent/steps-v/v-02a-validate-metadata.md +116 -116
- package/src/bmb/workflows/agent/steps-v/v-02b-validate-persona.md +124 -124
- package/src/bmb/workflows/agent/steps-v/v-02c-validate-menu.md +127 -127
- package/src/bmb/workflows/agent/steps-v/v-02d-validate-structure.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-02e-validate-sidecar.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-03-summary.md +104 -104
- package/src/bmb/workflows/agent/templates/agent-plan.template.md +5 -5
- package/src/bmb/workflows/agent/templates/agent-template.md +89 -89
- package/src/bmb/workflows/agent/workflow-create-agent.md +72 -72
- package/src/bmb/workflows/agent/workflow-edit-agent.md +75 -75
- package/src/bmb/workflows/agent/workflow-validate-agent.md +73 -73
- package/src/bmb/workflows/module/data/agent-architecture.md +179 -179
- package/src/bmb/workflows/module/data/agent-spec-template.md +79 -79
- package/src/bmb/workflows/module/data/module-standards.md +263 -263
- package/src/bmb/workflows/module/data/module-yaml-conventions.md +392 -392
- package/src/bmb/workflows/module/module-help-generate.md +254 -254
- package/src/bmb/workflows/module/steps-b/step-01-welcome.md +148 -148
- package/src/bmb/workflows/module/steps-b/step-02-spark.md +141 -141
- package/src/bmb/workflows/module/steps-b/step-03-module-type.md +149 -149
- package/src/bmb/workflows/module/steps-b/step-04-vision.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-05-identity.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-06-users.md +86 -86
- package/src/bmb/workflows/module/steps-b/step-07-value.md +76 -76
- package/src/bmb/workflows/module/steps-b/step-08-agents.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-09-workflows.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-10-tools.md +91 -91
- package/src/bmb/workflows/module/steps-b/step-11-scenarios.md +84 -84
- package/src/bmb/workflows/module/steps-b/step-12-creative.md +95 -95
- package/src/bmb/workflows/module/steps-b/step-13-review.md +105 -105
- package/src/bmb/workflows/module/steps-b/step-14-finalize.md +117 -117
- package/src/bmb/workflows/module/steps-c/step-01-load-brief.md +179 -179
- package/src/bmb/workflows/module/steps-c/step-01b-continue.md +82 -82
- package/src/bmb/workflows/module/steps-c/step-02-structure.md +105 -105
- package/src/bmb/workflows/module/steps-c/step-03-config.md +119 -119
- package/src/bmb/workflows/module/steps-c/step-04-agents.md +168 -168
- package/src/bmb/workflows/module/steps-c/step-05-workflows.md +184 -184
- package/src/bmb/workflows/module/steps-c/step-06-docs.md +401 -401
- package/src/bmb/workflows/module/steps-c/step-07-complete.md +152 -152
- package/src/bmb/workflows/module/steps-e/step-01-load-target.md +81 -81
- package/src/bmb/workflows/module/steps-e/step-02-select-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-03-apply-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-04-review.md +80 -80
- package/src/bmb/workflows/module/steps-e/step-05-confirm.md +75 -75
- package/src/bmb/workflows/module/steps-v/step-01-load-target.md +96 -96
- package/src/bmb/workflows/module/steps-v/step-02-file-structure.md +93 -93
- package/src/bmb/workflows/module/steps-v/step-03-module-yaml.md +99 -99
- package/src/bmb/workflows/module/steps-v/step-04-agent-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-05-workflow-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-06-documentation.md +143 -143
- package/src/bmb/workflows/module/steps-v/step-07-installation.md +102 -102
- package/src/bmb/workflows/module/steps-v/step-08-report.md +197 -197
- package/src/bmb/workflows/module/templates/brief-template.md +154 -154
- package/src/bmb/workflows/module/templates/workflow-spec-template.md +96 -96
- package/src/bmb/workflows/module/workflow-create-module-brief.md +71 -71
- package/src/bmb/workflows/module/workflow-create-module.md +86 -86
- package/src/bmb/workflows/module/workflow-edit-module.md +66 -66
- package/src/bmb/workflows/module/workflow-validate-module.md +66 -66
- package/src/bmb/workflows/workflow/data/architecture.md +150 -150
- package/src/bmb/workflows/workflow/data/common-workflow-tools.csv +19 -19
- package/src/bmb/workflows/workflow/data/csv-data-file-standards.md +53 -53
- package/src/bmb/workflows/workflow/data/frontmatter-standards.md +184 -184
- package/src/bmb/workflows/workflow/data/input-discovery-standards.md +191 -191
- package/src/bmb/workflows/workflow/data/intent-vs-prescriptive-spectrum.md +44 -44
- package/src/bmb/workflows/workflow/data/menu-handling-standards.md +133 -133
- package/src/bmb/workflows/workflow/data/output-format-standards.md +135 -135
- package/src/bmb/workflows/workflow/data/step-file-rules.md +235 -235
- package/src/bmb/workflows/workflow/data/step-type-patterns.md +257 -257
- package/src/bmb/workflows/workflow/data/subprocess-optimization-patterns.md +188 -188
- package/src/bmb/workflows/workflow/data/trimodal-workflow-structure.md +164 -164
- package/src/bmb/workflows/workflow/data/workflow-chaining-standards.md +222 -222
- package/src/bmb/workflows/workflow/data/workflow-examples.md +232 -232
- package/src/bmb/workflows/workflow/data/workflow-type-criteria.md +134 -134
- package/src/bmb/workflows/workflow/steps-c/step-00-conversion.md +263 -263
- package/src/bmb/workflows/workflow/steps-c/step-01-discovery.md +194 -194
- package/src/bmb/workflows/workflow/steps-c/step-01b-continuation.md +3 -3
- package/src/bmb/workflows/workflow/steps-c/step-02-classification.md +270 -270
- package/src/bmb/workflows/workflow/steps-c/step-03-requirements.md +283 -283
- package/src/bmb/workflows/workflow/steps-c/step-04-tools.md +282 -282
- package/src/bmb/workflows/workflow/steps-c/step-05-plan-review.md +243 -243
- package/src/bmb/workflows/workflow/steps-c/step-06-design.md +330 -330
- package/src/bmb/workflows/workflow/steps-c/step-07-foundation.md +239 -239
- package/src/bmb/workflows/workflow/steps-c/step-08-build-step-01.md +379 -379
- package/src/bmb/workflows/workflow/steps-c/step-09-build-next-step.md +350 -350
- package/src/bmb/workflows/workflow/steps-c/step-10-confirmation.md +322 -322
- package/src/bmb/workflows/workflow/steps-c/step-11-completion.md +191 -191
- package/src/bmb/workflows/workflow/steps-e/step-e-01-assess-workflow.md +237 -237
- package/src/bmb/workflows/workflow/steps-e/step-e-02-discover-edits.md +251 -251
- package/src/bmb/workflows/workflow/steps-e/step-e-03-fix-validation.md +254 -254
- package/src/bmb/workflows/workflow/steps-e/step-e-04-direct-edit.md +277 -277
- package/src/bmb/workflows/workflow/steps-e/step-e-05-apply-edit.md +154 -154
- package/src/bmb/workflows/workflow/steps-e/step-e-06-validate-after.md +190 -190
- package/src/bmb/workflows/workflow/steps-e/step-e-07-complete.md +206 -206
- package/src/bmb/workflows/workflow/steps-v/step-01-validate-max-mode.md +109 -109
- package/src/bmb/workflows/workflow/steps-v/step-01-validate.md +221 -221
- package/src/bmb/workflows/workflow/steps-v/step-01b-structure.md +152 -152
- package/src/bmb/workflows/workflow/steps-v/step-02-frontmatter-validation.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-02b-path-violations.md +265 -265
- package/src/bmb/workflows/workflow/steps-v/step-03-menu-validation.md +164 -164
- package/src/bmb/workflows/workflow/steps-v/step-04-step-type-validation.md +211 -211
- package/src/bmb/workflows/workflow/steps-v/step-05-output-format-validation.md +200 -200
- package/src/bmb/workflows/workflow/steps-v/step-06-validation-design-check.md +195 -195
- package/src/bmb/workflows/workflow/steps-v/step-07-instruction-style-check.md +209 -209
- package/src/bmb/workflows/workflow/steps-v/step-08-collaborative-experience-check.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-08b-subprocess-optimization.md +179 -179
- package/src/bmb/workflows/workflow/steps-v/step-09-cohesive-review.md +186 -186
- package/src/bmb/workflows/workflow/steps-v/step-10-report-complete.md +154 -154
- package/src/bmb/workflows/workflow/steps-v/step-11-plan-validation.md +237 -237
- package/src/bmb/workflows/workflow/templates/minimal-output-template.md +11 -11
- package/src/bmb/workflows/workflow/templates/step-01-init-continuable-template.md +241 -241
- package/src/bmb/workflows/workflow/templates/step-1b-template.md +224 -224
- package/src/bmb/workflows/workflow/templates/step-template.md +294 -294
- package/src/bmb/workflows/workflow/templates/workflow-template.md +102 -102
- package/src/bmb/workflows/workflow/workflow-create-workflow.md +79 -79
- package/src/bmb/workflows/workflow/workflow-edit-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-rework-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-validate-max-parallel-workflow.md +66 -66
- package/src/bmb/workflows/workflow/workflow-validate-workflow.md +65 -65
- package/src/bmm/agents/analyst.md +104 -104
- package/src/bmm/agents/dev.md +100 -100
- package/src/bmm/agents/qa.md +100 -90
- package/src/bmm/agents/tech-writer/tech-writer.md +94 -94
- package/src/bmm/module-help.csv +31 -31
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +115 -115
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +107 -107
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +141 -141
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +144 -144
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +147 -147
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +161 -161
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +99 -99
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -57
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +156 -156
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +165 -165
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +140 -140
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +152 -152
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +345 -345
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +92 -92
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +164 -164
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +174 -174
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +184 -184
- package/src/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +105 -105
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +360 -360
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +165 -165
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +174 -174
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +141 -141
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +159 -159
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +387 -387
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -54
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +100 -100
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +160 -160
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +88 -88
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +99 -99
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +169 -169
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +156 -156
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +176 -176
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +184 -184
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +174 -174
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +175 -175
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +189 -189
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +162 -162
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +79 -79
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +183 -183
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +149 -149
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +187 -187
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +108 -108
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +166 -166
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +131 -131
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +150 -150
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +155 -155
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +170 -170
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +158 -158
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +147 -147
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +182 -182
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +202 -202
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +148 -148
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +201 -201
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +179 -179
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +164 -164
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +106 -106
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +111 -111
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +115 -115
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +127 -127
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +167 -167
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +143 -143
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +154 -154
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +165 -165
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +135 -135
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +101 -101
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +45 -45
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +185 -185
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +130 -130
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +93 -93
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +196 -196
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -54
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +82 -82
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +106 -106
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +138 -138
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +129 -129
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +166 -166
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +186 -186
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +163 -163
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +38 -38
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -49
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +124 -124
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +122 -122
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +84 -84
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -58
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +43 -43
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +53 -53
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +159 -159
- package/src/bmm/workflows/4-implementation/create-story/template.md +79 -79
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +20 -20
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -25
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +158 -158
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +122 -122
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +87 -87
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -146
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -50
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +152 -152
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +123 -123
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +201 -201
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -79
- package/src/bmm/workflows/document-project/workflow.yaml +22 -22
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -184
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +322 -322
- package/src/bmm/workflows/generate-project-context/steps/step-03-complete.md +235 -235
- package/src/bmm/workflows/generate-project-context/workflow.md +49 -49
- package/src/bmm/workflows/qa/automate/workflow.yaml +233 -233
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +42 -42
- package/src/core/config.yaml +9 -9
- package/src/core/module-help.csv +10 -10
- package/src/core/scripts/generate-loop-report.py +72 -72
- package/src/core/tasks/editorial-review-prose.xml +101 -101
- package/src/core/tasks/editorial-review-structure.xml +207 -207
- package/src/core/tasks/help.md +86 -86
- package/src/core/tasks/index-docs.xml +64 -64
- package/src/core/tasks/review-adversarial-general.xml +66 -66
- package/src/core/tasks/review-adversarial-loop.xml +46 -46
- package/src/core/tasks/review-edge-case-hunter.xml +63 -63
- package/src/core/tasks/review-party-loop.xml +46 -46
- package/src/core/tasks/shard-doc.xml +107 -107
- package/src/core/tasks/workflow.xml +235 -235
- package/src/core/templates/review-loop-report.html +88 -88
- package/src/core/templates/review-loop-report.md +5 -5
- package/src/core/workflows/advanced-elicitation/workflow.xml +117 -117
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +212 -212
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -122
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -225
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -237
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -209
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -264
- package/src/core/workflows/brainstorming/steps/step-02e-deep-dive.md +68 -68
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +403 -403
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -303
- package/src/core/workflows/brainstorming/workflow.md +60 -60
- package/src/core/workflows/extract-trackers/workflow.md +45 -45
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +142 -142
- package/src/core/workflows/party-mode/workflow.md +194 -194
- package/src/docs/dev/tmux/actions_popup.py +291 -291
- package/src/docs/dev/tmux/tmux-setup.md +62 -1
|
@@ -1,595 +1,595 @@
|
|
|
1
|
-
# Jetpack Compose View Composition Reference
|
|
2
|
-
|
|
3
|
-
## Composable Function Naming Conventions
|
|
4
|
-
|
|
5
|
-
Names communicate intent. Follow these patterns consistently.
|
|
6
|
-
|
|
7
|
-
### Nouns (UI Components)
|
|
8
|
-
- PascalCase, describe *what* the composable displays
|
|
9
|
-
- Used for UI widgets, screens, layout building blocks
|
|
10
|
-
|
|
11
|
-
```kotlin
|
|
12
|
-
@Composable
|
|
13
|
-
fun Button(...) // Displays a button
|
|
14
|
-
|
|
15
|
-
@Composable
|
|
16
|
-
fun UserCard(user: User) // Displays a user card
|
|
17
|
-
|
|
18
|
-
@Composable
|
|
19
|
-
fun LoginScreen() // Displays a login screen
|
|
20
|
-
|
|
21
|
-
@Composable
|
|
22
|
-
fun CheckboxWithLabel(...) // Displays a checkbox with label
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Verbs (Side Effects / Effects)
|
|
26
|
-
- PascalCase, describe *what action* happens
|
|
27
|
-
- Used for composables that don't emit UI, only perform side effects
|
|
28
|
-
|
|
29
|
-
```kotlin
|
|
30
|
-
@Composable
|
|
31
|
-
fun LaunchedEffect(...) // Launches a coroutine
|
|
32
|
-
|
|
33
|
-
@Composable
|
|
34
|
-
fun DisposableEffect(...) // Manages resource lifecycle
|
|
35
|
-
|
|
36
|
-
@Composable
|
|
37
|
-
fun SideEffect(...) // Performs a side effect
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Anti-Pattern: Ambiguous Names
|
|
41
|
-
```kotlin
|
|
42
|
-
// ❌ Unclear if this is a UI component or effect
|
|
43
|
-
@Composable
|
|
44
|
-
fun HandleLogin(...)
|
|
45
|
-
|
|
46
|
-
// ✅ Explicit
|
|
47
|
-
@Composable
|
|
48
|
-
fun LoginScreen(...) // Displays UI
|
|
49
|
-
|
|
50
|
-
@Composable
|
|
51
|
-
fun PerformLogin(...) // Side effect function (if truly a side effect)
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## The Slot Pattern
|
|
55
|
-
|
|
56
|
-
Accept `@Composable` lambda parameters to create flexible, reusable containers.
|
|
57
|
-
|
|
58
|
-
### Basic Slot Pattern
|
|
59
|
-
```kotlin
|
|
60
|
-
@Composable
|
|
61
|
-
fun Card(
|
|
62
|
-
modifier: Modifier = Modifier,
|
|
63
|
-
content: @Composable () -> Unit
|
|
64
|
-
) {
|
|
65
|
-
Box(
|
|
66
|
-
modifier = modifier
|
|
67
|
-
.background(Color.White)
|
|
68
|
-
.padding(16.dp)
|
|
69
|
-
) {
|
|
70
|
-
content()
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Usage
|
|
75
|
-
Card {
|
|
76
|
-
Text("Hello")
|
|
77
|
-
Image(...)
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Multiple Slots
|
|
82
|
-
```kotlin
|
|
83
|
-
@Composable
|
|
84
|
-
fun ListItem(
|
|
85
|
-
modifier: Modifier = Modifier,
|
|
86
|
-
icon: @Composable () -> Unit,
|
|
87
|
-
title: @Composable () -> Unit,
|
|
88
|
-
subtitle: @Composable (() -> Unit)? = null,
|
|
89
|
-
trailing: @Composable (() -> Unit)? = null
|
|
90
|
-
) {
|
|
91
|
-
Row(modifier = modifier.padding(16.dp)) {
|
|
92
|
-
icon()
|
|
93
|
-
Column(modifier = Modifier.weight(1f)) {
|
|
94
|
-
title()
|
|
95
|
-
subtitle?.invoke()
|
|
96
|
-
}
|
|
97
|
-
trailing?.invoke()
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Usage
|
|
102
|
-
ListItem(
|
|
103
|
-
icon = { Icon(Icons.Default.Person, "") },
|
|
104
|
-
title = { Text("Alice") },
|
|
105
|
-
subtitle = { Text("Online") },
|
|
106
|
-
trailing = { Badge() }
|
|
107
|
-
)
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
**Key principle:** Slots accept `@Composable` lambdas, not pre-composed values. This ensures composition is deferred and scope-aware.
|
|
111
|
-
|
|
112
|
-
```kotlin
|
|
113
|
-
// ❌ Wrong: passes composed value
|
|
114
|
-
fun CustomLayout(content: String) { ... }
|
|
115
|
-
|
|
116
|
-
// ✅ Correct: passes composition lambda
|
|
117
|
-
fun CustomLayout(content: @Composable () -> Unit) { ... }
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Source: Material 3 composables in `androidx.compose.material3` use slots extensively.
|
|
121
|
-
|
|
122
|
-
## Extracting Composables
|
|
123
|
-
|
|
124
|
-
Know when to extract and when to keep composables together.
|
|
125
|
-
|
|
126
|
-
### Extract When
|
|
127
|
-
- **Reused in multiple places:** DRY principle
|
|
128
|
-
- **Single responsibility:** Composable handles one concern
|
|
129
|
-
- **Easier to test:** Small, focused unit
|
|
130
|
-
- **Performance:** Enables skipping and independent recomposition
|
|
131
|
-
|
|
132
|
-
```kotlin
|
|
133
|
-
// ❌ Before: god composable
|
|
134
|
-
@Composable
|
|
135
|
-
fun UserProfile(user: User) {
|
|
136
|
-
Column {
|
|
137
|
-
// Header
|
|
138
|
-
Box(modifier = Modifier.fillMaxWidth()) {
|
|
139
|
-
Image(user.photo)
|
|
140
|
-
Text(user.name, style = MaterialTheme.typography.headlineSmall)
|
|
141
|
-
IconButton({ /* edit */ }) { Icon(Icons.Default.Edit, "") }
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Stats
|
|
145
|
-
Row(modifier = Modifier.fillMaxWidth()) {
|
|
146
|
-
StatItem(user.followers, "Followers")
|
|
147
|
-
StatItem(user.following, "Following")
|
|
148
|
-
StatItem(user.posts, "Posts")
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Bio
|
|
152
|
-
Text(user.bio, style = MaterialTheme.typography.bodyMedium)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ✅ After: extracted composables
|
|
157
|
-
@Composable
|
|
158
|
-
fun UserProfile(user: User) {
|
|
159
|
-
Column {
|
|
160
|
-
UserProfileHeader(user)
|
|
161
|
-
UserStats(user)
|
|
162
|
-
UserBio(user.bio)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@Composable
|
|
167
|
-
private fun UserProfileHeader(user: User) { ... }
|
|
168
|
-
|
|
169
|
-
@Composable
|
|
170
|
-
private fun UserStats(user: User) { ... }
|
|
171
|
-
|
|
172
|
-
@Composable
|
|
173
|
-
private fun UserBio(bio: String) { ... }
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Don't Extract When
|
|
177
|
-
- **Single use:** Extraction adds indirection without benefit
|
|
178
|
-
- **Tightly coupled logic:** Would require passing many parameters
|
|
179
|
-
- **Too small:** Single `Text()` or `Icon()` doesn't need extraction
|
|
180
|
-
|
|
181
|
-
```kotlin
|
|
182
|
-
// ❌ Over-extraction: trivial wrapper
|
|
183
|
-
@Composable
|
|
184
|
-
private fun UserName(name: String) {
|
|
185
|
-
Text(name, style = MaterialTheme.typography.headlineSmall)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// ✅ Keep inline if only used once
|
|
189
|
-
@Composable
|
|
190
|
-
fun UserProfile(user: User) {
|
|
191
|
-
Text(user.name, style = MaterialTheme.typography.headlineSmall)
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## Stateful vs Stateless Composables
|
|
196
|
-
|
|
197
|
-
Structure composables as a stateless layer with optional stateful wrapper.
|
|
198
|
-
|
|
199
|
-
### Pattern: Stateless + Wrapper
|
|
200
|
-
|
|
201
|
-
```kotlin
|
|
202
|
-
// ✅ Stateless composable (reusable, testable)
|
|
203
|
-
@Composable
|
|
204
|
-
fun ToggleButton(
|
|
205
|
-
isEnabled: Boolean,
|
|
206
|
-
onToggle: (Boolean) -> Unit,
|
|
207
|
-
text: String
|
|
208
|
-
) {
|
|
209
|
-
Button(
|
|
210
|
-
onClick = { onToggle(!isEnabled) },
|
|
211
|
-
colors = ButtonDefaults.buttonColors(
|
|
212
|
-
containerColor = if (isEnabled) Color.Blue else Color.Gray
|
|
213
|
-
)
|
|
214
|
-
) {
|
|
215
|
-
Text(text)
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// ✅ Stateful wrapper (manages state, uses stateless child)
|
|
220
|
-
@Composable
|
|
221
|
-
fun StatefulToggleButton(text: String = "Toggle") {
|
|
222
|
-
var isEnabled by remember { mutableStateOf(false) }
|
|
223
|
-
ToggleButton(
|
|
224
|
-
isEnabled = isEnabled,
|
|
225
|
-
onToggle = { isEnabled = it },
|
|
226
|
-
text = text
|
|
227
|
-
)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Usage: choose based on need
|
|
231
|
-
@Composable
|
|
232
|
-
fun MyScreen() {
|
|
233
|
-
// Use stateless when caller manages state
|
|
234
|
-
var featureEnabled by remember { mutableStateOf(false) }
|
|
235
|
-
ToggleButton(featureEnabled, { featureEnabled = it }, "Feature")
|
|
236
|
-
|
|
237
|
-
// Use stateful wrapper for isolated state
|
|
238
|
-
StatefulToggleButton("Local Toggle")
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
**Advantage:** Caller can test and reuse `ToggleButton` without mocking state. `StatefulToggleButton` provides convenience for simple cases.
|
|
243
|
-
|
|
244
|
-
## Preview Annotations
|
|
245
|
-
|
|
246
|
-
Use previews for rapid UI development and regression testing.
|
|
247
|
-
|
|
248
|
-
### @Preview
|
|
249
|
-
Basic preview of a single composable.
|
|
250
|
-
|
|
251
|
-
```kotlin
|
|
252
|
-
@Preview
|
|
253
|
-
@Composable
|
|
254
|
-
fun UserCardPreview() {
|
|
255
|
-
UserCard(user = User(1, "Alice"))
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Multiple previews
|
|
259
|
-
@Preview(name = "Light")
|
|
260
|
-
@Preview(name = "Dark", uiMode = UI_MODE_NIGHT_YES)
|
|
261
|
-
@Composable
|
|
262
|
-
fun UserCardPreviews() {
|
|
263
|
-
UserCard(user = User(1, "Alice"))
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### @PreviewLightDark
|
|
268
|
-
Automatically generates light and dark theme previews.
|
|
269
|
-
|
|
270
|
-
```kotlin
|
|
271
|
-
@PreviewLightDark
|
|
272
|
-
@Composable
|
|
273
|
-
fun UserCardPreview() {
|
|
274
|
-
MyTheme {
|
|
275
|
-
UserCard(user = User(1, "Alice"))
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### @PreviewFontScale
|
|
281
|
-
Shows how composable responds to different font sizes.
|
|
282
|
-
|
|
283
|
-
```kotlin
|
|
284
|
-
@Preview(fontScale = 0.8f, name = "Small Fonts")
|
|
285
|
-
@Preview(fontScale = 1f, name = "Normal Fonts")
|
|
286
|
-
@Preview(fontScale = 1.2f, name = "Large Fonts")
|
|
287
|
-
@Composable
|
|
288
|
-
fun TextPreview() {
|
|
289
|
-
Text("This is text")
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
### @PreviewScreenSizes
|
|
294
|
-
Tests multiple screen dimensions.
|
|
295
|
-
|
|
296
|
-
```kotlin
|
|
297
|
-
@Preview(device = Devices.PHONE, name = "Phone")
|
|
298
|
-
@Preview(device = Devices.TABLET, name = "Tablet")
|
|
299
|
-
@Preview(device = Devices.FOLDABLE, name = "Foldable")
|
|
300
|
-
@Composable
|
|
301
|
-
fun ResponsiveLayoutPreview() {
|
|
302
|
-
ResponsiveLayout()
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
Source: `androidx.compose.ui.tooling.preview`
|
|
307
|
-
|
|
308
|
-
## CompositionLocal
|
|
309
|
-
|
|
310
|
-
Provide implicit parameters without threading them through the hierarchy.
|
|
311
|
-
|
|
312
|
-
### When to Use
|
|
313
|
-
- **Theming:** Pass `Colors`, `Typography` implicitly
|
|
314
|
-
- **Navigation:** Access from deep in composable tree
|
|
315
|
-
- **Locale/Strings:** Avoid passing through every composable
|
|
316
|
-
|
|
317
|
-
```kotlin
|
|
318
|
-
// ✅ Define at top level
|
|
319
|
-
val LocalUser = staticCompositionLocalOf<User?> { null }
|
|
320
|
-
|
|
321
|
-
@Composable
|
|
322
|
-
fun App(user: User) {
|
|
323
|
-
CompositionLocalProvider(LocalUser provides user) {
|
|
324
|
-
MainContent()
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// ✅ Access deep in tree without passing through every composable
|
|
329
|
-
@Composable
|
|
330
|
-
fun UserGreeting() {
|
|
331
|
-
val user = LocalUser.current
|
|
332
|
-
Text("Hello, ${user?.name}")
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### When NOT to Use
|
|
337
|
-
- **Configuration params:** If only 1-2 levels deep, pass directly
|
|
338
|
-
- **Frequently changing values:** Can cause unnecessary recomposition
|
|
339
|
-
- **Dependencies:** Use dependency injection at ViewModel level
|
|
340
|
-
|
|
341
|
-
```kotlin
|
|
342
|
-
// ❌ Over-use: should pass `title` directly
|
|
343
|
-
val LocalTitle = staticCompositionLocalOf<String> { "" }
|
|
344
|
-
|
|
345
|
-
@Composable
|
|
346
|
-
fun Parent() {
|
|
347
|
-
CompositionLocalProvider(LocalTitle provides "My Title") {
|
|
348
|
-
Child()
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// ✅ Just pass it
|
|
353
|
-
@Composable
|
|
354
|
-
fun Parent(title: String) {
|
|
355
|
-
Child(title = title)
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
@Composable
|
|
359
|
-
fun Child(title: String) { ... }
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
**Types:**
|
|
363
|
-
- `staticCompositionLocalOf`: Value rarely changes, default is a constant
|
|
364
|
-
- `compositionLocalOf`: Value changes frequently, default is computed
|
|
365
|
-
|
|
366
|
-
## Composable Return Values
|
|
367
|
-
|
|
368
|
-
**Never return values from composables.** Use callbacks instead.
|
|
369
|
-
|
|
370
|
-
```kotlin
|
|
371
|
-
// ❌ Wrong: composables don't return values
|
|
372
|
-
@Composable
|
|
373
|
-
fun UserInput(): String {
|
|
374
|
-
var text by remember { mutableStateOf("") }
|
|
375
|
-
return text // Can't do this
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// ✅ Correct: callback pattern
|
|
379
|
-
@Composable
|
|
380
|
-
fun UserInput(onUserInput: (String) -> Unit) {
|
|
381
|
-
var text by remember { mutableStateOf("") }
|
|
382
|
-
TextField(
|
|
383
|
-
value = text,
|
|
384
|
-
onValueChange = {
|
|
385
|
-
text = it
|
|
386
|
-
onUserInput(it) // Notify parent
|
|
387
|
-
}
|
|
388
|
-
)
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Usage
|
|
392
|
-
@Composable
|
|
393
|
-
fun FormScreen() {
|
|
394
|
-
UserInput(onUserInput = { input -> /* handle */ })
|
|
395
|
-
}
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
**Rationale:** Composables are executed during composition, which happens at unpredictable times and may be skipped or reordered.
|
|
399
|
-
|
|
400
|
-
## Screen-Level Composables
|
|
401
|
-
|
|
402
|
-
Structure screens as a thin ViewModel integration layer above pure composables.
|
|
403
|
-
|
|
404
|
-
### Recommended Pattern
|
|
405
|
-
```kotlin
|
|
406
|
-
// ✅ Screen composable: connects ViewModel
|
|
407
|
-
@Composable
|
|
408
|
-
fun UserDetailsScreen(
|
|
409
|
-
viewModel: UserDetailsViewModel = hiltViewModel(),
|
|
410
|
-
userId: String
|
|
411
|
-
) {
|
|
412
|
-
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
|
413
|
-
LaunchedEffect(userId) {
|
|
414
|
-
viewModel.loadUser(userId)
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
UserDetailsContent(
|
|
418
|
-
uiState = uiState,
|
|
419
|
-
onRetry = { viewModel.loadUser(userId) }
|
|
420
|
-
)
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// ✅ Content composable: pure (testable, reusable)
|
|
424
|
-
@Composable
|
|
425
|
-
private fun UserDetailsContent(
|
|
426
|
-
uiState: UiState,
|
|
427
|
-
onRetry: () -> Unit
|
|
428
|
-
) {
|
|
429
|
-
when (uiState) {
|
|
430
|
-
is UiState.Loading -> LoadingUI()
|
|
431
|
-
is UiState.Success -> SuccessUI(uiState.user)
|
|
432
|
-
is UiState.Error -> ErrorUI(uiState.message, onRetry)
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// ✅ Composable for preview/testing
|
|
437
|
-
@Preview
|
|
438
|
-
@Composable
|
|
439
|
-
private fun UserDetailsContentPreview() {
|
|
440
|
-
UserDetailsContent(
|
|
441
|
-
uiState = UiState.Success(User(1, "Alice")),
|
|
442
|
-
onRetry = {}
|
|
443
|
-
)
|
|
444
|
-
}
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
**Benefits:**
|
|
448
|
-
- Public screen composable integrates ViewModel
|
|
449
|
-
- Private content composable is pure, testable, previewable
|
|
450
|
-
- Clear separation: UI logic (public) vs rendering (private)
|
|
451
|
-
|
|
452
|
-
**Anti-pattern:** Passing ViewModel to child composables. Keep it at screen level only.
|
|
453
|
-
|
|
454
|
-
```kotlin
|
|
455
|
-
// ❌ Couples child to ViewModel
|
|
456
|
-
@Composable
|
|
457
|
-
fun UserCard(viewModel: UserViewModel) {
|
|
458
|
-
val user by viewModel.user.collectAsStateWithLifecycle()
|
|
459
|
-
Text(user.name)
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// ✅ Pass only the data
|
|
463
|
-
@Composable
|
|
464
|
-
fun UserCard(user: User) {
|
|
465
|
-
Text(user.name)
|
|
466
|
-
}
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
## Reusability Guidelines
|
|
470
|
-
|
|
471
|
-
Design composables to be configurable without over-parameterization.
|
|
472
|
-
|
|
473
|
-
### Configuration via Parameters
|
|
474
|
-
```kotlin
|
|
475
|
-
// ✅ Expose what varies, hide what doesn't
|
|
476
|
-
@Composable
|
|
477
|
-
fun Card(
|
|
478
|
-
modifier: Modifier = Modifier,
|
|
479
|
-
content: @Composable () -> Unit
|
|
480
|
-
) {
|
|
481
|
-
// Internal: fixed styling, padding, etc.
|
|
482
|
-
Box(
|
|
483
|
-
modifier = modifier
|
|
484
|
-
.background(Color.White)
|
|
485
|
-
.padding(16.dp)
|
|
486
|
-
.clip(RoundedCornerShape(8.dp))
|
|
487
|
-
) {
|
|
488
|
-
content()
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Avoid Parameter Explosion
|
|
494
|
-
```kotlin
|
|
495
|
-
// ❌ Too many parameters, hard to use
|
|
496
|
-
@Composable
|
|
497
|
-
fun Button(
|
|
498
|
-
text: String,
|
|
499
|
-
textColor: Color,
|
|
500
|
-
backgroundColor: Color,
|
|
501
|
-
cornerRadius: Dp,
|
|
502
|
-
padding: PaddingValues,
|
|
503
|
-
elevation: Dp,
|
|
504
|
-
...
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
// ✅ Sensible defaults, style objects
|
|
508
|
-
@Composable
|
|
509
|
-
fun Button(
|
|
510
|
-
text: String,
|
|
511
|
-
modifier: Modifier = Modifier,
|
|
512
|
-
style: ButtonStyle = ButtonStyle.Primary,
|
|
513
|
-
onClick: () -> Unit
|
|
514
|
-
) { ... }
|
|
515
|
-
|
|
516
|
-
// Or: use Material composables with built-in styles
|
|
517
|
-
@Composable
|
|
518
|
-
fun Button(
|
|
519
|
-
onClick: () -> Unit,
|
|
520
|
-
modifier: Modifier = Modifier,
|
|
521
|
-
enabled: Boolean = true,
|
|
522
|
-
...
|
|
523
|
-
) { ... } // Material3 Button has reasonable defaults
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
## Common Anti-Patterns
|
|
527
|
-
|
|
528
|
-
### God Composables
|
|
529
|
-
```kotlin
|
|
530
|
-
// ❌ Does too much
|
|
531
|
-
@Composable
|
|
532
|
-
fun Dashboard() {
|
|
533
|
-
// Header
|
|
534
|
-
Box { /* 20 lines */ }
|
|
535
|
-
|
|
536
|
-
// List
|
|
537
|
-
LazyColumn {
|
|
538
|
-
items(items) { /* 15 lines */ }
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// Footer
|
|
542
|
-
Box { /* 15 lines */ }
|
|
543
|
-
|
|
544
|
-
// Dialogs, side effects, state management...
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// ✅ Extract and delegate
|
|
548
|
-
@Composable
|
|
549
|
-
fun Dashboard() {
|
|
550
|
-
Column {
|
|
551
|
-
DashboardHeader()
|
|
552
|
-
DashboardContent()
|
|
553
|
-
DashboardFooter()
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
### Deep Nesting
|
|
559
|
-
```kotlin
|
|
560
|
-
// ❌ Hard to read and debug
|
|
561
|
-
@Composable
|
|
562
|
-
fun LoginScreen() {
|
|
563
|
-
Box { Column { Row { Card { Box { Text { ... } } } } } }
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// ✅ Intermediate variables and extraction
|
|
567
|
-
@Composable
|
|
568
|
-
fun LoginScreen() {
|
|
569
|
-
val form = loginFormState()
|
|
570
|
-
Column {
|
|
571
|
-
LoginForm(form)
|
|
572
|
-
LoginButton(form)
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
### Passing ViewModel to Children
|
|
578
|
-
```kotlin
|
|
579
|
-
// ❌ Violates composition boundaries
|
|
580
|
-
@Composable
|
|
581
|
-
fun ParentScreen(viewModel: ParentViewModel) {
|
|
582
|
-
ChildCard(viewModel = viewModel) // Don't do this
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// ✅ Extract data, pass to child
|
|
586
|
-
@Composable
|
|
587
|
-
fun ParentScreen(viewModel: ParentViewModel) {
|
|
588
|
-
val data by viewModel.data.collectAsStateWithLifecycle()
|
|
589
|
-
ChildCard(data = data)
|
|
590
|
-
}
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
---
|
|
594
|
-
|
|
595
|
-
**Source references:** `androidx.compose.material3`, `androidx.compose.ui.tooling.preview`, `androidx.compose.runtime.CompositionLocal`
|
|
1
|
+
# Jetpack Compose View Composition Reference
|
|
2
|
+
|
|
3
|
+
## Composable Function Naming Conventions
|
|
4
|
+
|
|
5
|
+
Names communicate intent. Follow these patterns consistently.
|
|
6
|
+
|
|
7
|
+
### Nouns (UI Components)
|
|
8
|
+
- PascalCase, describe *what* the composable displays
|
|
9
|
+
- Used for UI widgets, screens, layout building blocks
|
|
10
|
+
|
|
11
|
+
```kotlin
|
|
12
|
+
@Composable
|
|
13
|
+
fun Button(...) // Displays a button
|
|
14
|
+
|
|
15
|
+
@Composable
|
|
16
|
+
fun UserCard(user: User) // Displays a user card
|
|
17
|
+
|
|
18
|
+
@Composable
|
|
19
|
+
fun LoginScreen() // Displays a login screen
|
|
20
|
+
|
|
21
|
+
@Composable
|
|
22
|
+
fun CheckboxWithLabel(...) // Displays a checkbox with label
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Verbs (Side Effects / Effects)
|
|
26
|
+
- PascalCase, describe *what action* happens
|
|
27
|
+
- Used for composables that don't emit UI, only perform side effects
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
@Composable
|
|
31
|
+
fun LaunchedEffect(...) // Launches a coroutine
|
|
32
|
+
|
|
33
|
+
@Composable
|
|
34
|
+
fun DisposableEffect(...) // Manages resource lifecycle
|
|
35
|
+
|
|
36
|
+
@Composable
|
|
37
|
+
fun SideEffect(...) // Performs a side effect
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Anti-Pattern: Ambiguous Names
|
|
41
|
+
```kotlin
|
|
42
|
+
// ❌ Unclear if this is a UI component or effect
|
|
43
|
+
@Composable
|
|
44
|
+
fun HandleLogin(...)
|
|
45
|
+
|
|
46
|
+
// ✅ Explicit
|
|
47
|
+
@Composable
|
|
48
|
+
fun LoginScreen(...) // Displays UI
|
|
49
|
+
|
|
50
|
+
@Composable
|
|
51
|
+
fun PerformLogin(...) // Side effect function (if truly a side effect)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## The Slot Pattern
|
|
55
|
+
|
|
56
|
+
Accept `@Composable` lambda parameters to create flexible, reusable containers.
|
|
57
|
+
|
|
58
|
+
### Basic Slot Pattern
|
|
59
|
+
```kotlin
|
|
60
|
+
@Composable
|
|
61
|
+
fun Card(
|
|
62
|
+
modifier: Modifier = Modifier,
|
|
63
|
+
content: @Composable () -> Unit
|
|
64
|
+
) {
|
|
65
|
+
Box(
|
|
66
|
+
modifier = modifier
|
|
67
|
+
.background(Color.White)
|
|
68
|
+
.padding(16.dp)
|
|
69
|
+
) {
|
|
70
|
+
content()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Usage
|
|
75
|
+
Card {
|
|
76
|
+
Text("Hello")
|
|
77
|
+
Image(...)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Multiple Slots
|
|
82
|
+
```kotlin
|
|
83
|
+
@Composable
|
|
84
|
+
fun ListItem(
|
|
85
|
+
modifier: Modifier = Modifier,
|
|
86
|
+
icon: @Composable () -> Unit,
|
|
87
|
+
title: @Composable () -> Unit,
|
|
88
|
+
subtitle: @Composable (() -> Unit)? = null,
|
|
89
|
+
trailing: @Composable (() -> Unit)? = null
|
|
90
|
+
) {
|
|
91
|
+
Row(modifier = modifier.padding(16.dp)) {
|
|
92
|
+
icon()
|
|
93
|
+
Column(modifier = Modifier.weight(1f)) {
|
|
94
|
+
title()
|
|
95
|
+
subtitle?.invoke()
|
|
96
|
+
}
|
|
97
|
+
trailing?.invoke()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Usage
|
|
102
|
+
ListItem(
|
|
103
|
+
icon = { Icon(Icons.Default.Person, "") },
|
|
104
|
+
title = { Text("Alice") },
|
|
105
|
+
subtitle = { Text("Online") },
|
|
106
|
+
trailing = { Badge() }
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Key principle:** Slots accept `@Composable` lambdas, not pre-composed values. This ensures composition is deferred and scope-aware.
|
|
111
|
+
|
|
112
|
+
```kotlin
|
|
113
|
+
// ❌ Wrong: passes composed value
|
|
114
|
+
fun CustomLayout(content: String) { ... }
|
|
115
|
+
|
|
116
|
+
// ✅ Correct: passes composition lambda
|
|
117
|
+
fun CustomLayout(content: @Composable () -> Unit) { ... }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Source: Material 3 composables in `androidx.compose.material3` use slots extensively.
|
|
121
|
+
|
|
122
|
+
## Extracting Composables
|
|
123
|
+
|
|
124
|
+
Know when to extract and when to keep composables together.
|
|
125
|
+
|
|
126
|
+
### Extract When
|
|
127
|
+
- **Reused in multiple places:** DRY principle
|
|
128
|
+
- **Single responsibility:** Composable handles one concern
|
|
129
|
+
- **Easier to test:** Small, focused unit
|
|
130
|
+
- **Performance:** Enables skipping and independent recomposition
|
|
131
|
+
|
|
132
|
+
```kotlin
|
|
133
|
+
// ❌ Before: god composable
|
|
134
|
+
@Composable
|
|
135
|
+
fun UserProfile(user: User) {
|
|
136
|
+
Column {
|
|
137
|
+
// Header
|
|
138
|
+
Box(modifier = Modifier.fillMaxWidth()) {
|
|
139
|
+
Image(user.photo)
|
|
140
|
+
Text(user.name, style = MaterialTheme.typography.headlineSmall)
|
|
141
|
+
IconButton({ /* edit */ }) { Icon(Icons.Default.Edit, "") }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Stats
|
|
145
|
+
Row(modifier = Modifier.fillMaxWidth()) {
|
|
146
|
+
StatItem(user.followers, "Followers")
|
|
147
|
+
StatItem(user.following, "Following")
|
|
148
|
+
StatItem(user.posts, "Posts")
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Bio
|
|
152
|
+
Text(user.bio, style = MaterialTheme.typography.bodyMedium)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ✅ After: extracted composables
|
|
157
|
+
@Composable
|
|
158
|
+
fun UserProfile(user: User) {
|
|
159
|
+
Column {
|
|
160
|
+
UserProfileHeader(user)
|
|
161
|
+
UserStats(user)
|
|
162
|
+
UserBio(user.bio)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@Composable
|
|
167
|
+
private fun UserProfileHeader(user: User) { ... }
|
|
168
|
+
|
|
169
|
+
@Composable
|
|
170
|
+
private fun UserStats(user: User) { ... }
|
|
171
|
+
|
|
172
|
+
@Composable
|
|
173
|
+
private fun UserBio(bio: String) { ... }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Don't Extract When
|
|
177
|
+
- **Single use:** Extraction adds indirection without benefit
|
|
178
|
+
- **Tightly coupled logic:** Would require passing many parameters
|
|
179
|
+
- **Too small:** Single `Text()` or `Icon()` doesn't need extraction
|
|
180
|
+
|
|
181
|
+
```kotlin
|
|
182
|
+
// ❌ Over-extraction: trivial wrapper
|
|
183
|
+
@Composable
|
|
184
|
+
private fun UserName(name: String) {
|
|
185
|
+
Text(name, style = MaterialTheme.typography.headlineSmall)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ✅ Keep inline if only used once
|
|
189
|
+
@Composable
|
|
190
|
+
fun UserProfile(user: User) {
|
|
191
|
+
Text(user.name, style = MaterialTheme.typography.headlineSmall)
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Stateful vs Stateless Composables
|
|
196
|
+
|
|
197
|
+
Structure composables as a stateless layer with optional stateful wrapper.
|
|
198
|
+
|
|
199
|
+
### Pattern: Stateless + Wrapper
|
|
200
|
+
|
|
201
|
+
```kotlin
|
|
202
|
+
// ✅ Stateless composable (reusable, testable)
|
|
203
|
+
@Composable
|
|
204
|
+
fun ToggleButton(
|
|
205
|
+
isEnabled: Boolean,
|
|
206
|
+
onToggle: (Boolean) -> Unit,
|
|
207
|
+
text: String
|
|
208
|
+
) {
|
|
209
|
+
Button(
|
|
210
|
+
onClick = { onToggle(!isEnabled) },
|
|
211
|
+
colors = ButtonDefaults.buttonColors(
|
|
212
|
+
containerColor = if (isEnabled) Color.Blue else Color.Gray
|
|
213
|
+
)
|
|
214
|
+
) {
|
|
215
|
+
Text(text)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ✅ Stateful wrapper (manages state, uses stateless child)
|
|
220
|
+
@Composable
|
|
221
|
+
fun StatefulToggleButton(text: String = "Toggle") {
|
|
222
|
+
var isEnabled by remember { mutableStateOf(false) }
|
|
223
|
+
ToggleButton(
|
|
224
|
+
isEnabled = isEnabled,
|
|
225
|
+
onToggle = { isEnabled = it },
|
|
226
|
+
text = text
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Usage: choose based on need
|
|
231
|
+
@Composable
|
|
232
|
+
fun MyScreen() {
|
|
233
|
+
// Use stateless when caller manages state
|
|
234
|
+
var featureEnabled by remember { mutableStateOf(false) }
|
|
235
|
+
ToggleButton(featureEnabled, { featureEnabled = it }, "Feature")
|
|
236
|
+
|
|
237
|
+
// Use stateful wrapper for isolated state
|
|
238
|
+
StatefulToggleButton("Local Toggle")
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Advantage:** Caller can test and reuse `ToggleButton` without mocking state. `StatefulToggleButton` provides convenience for simple cases.
|
|
243
|
+
|
|
244
|
+
## Preview Annotations
|
|
245
|
+
|
|
246
|
+
Use previews for rapid UI development and regression testing.
|
|
247
|
+
|
|
248
|
+
### @Preview
|
|
249
|
+
Basic preview of a single composable.
|
|
250
|
+
|
|
251
|
+
```kotlin
|
|
252
|
+
@Preview
|
|
253
|
+
@Composable
|
|
254
|
+
fun UserCardPreview() {
|
|
255
|
+
UserCard(user = User(1, "Alice"))
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Multiple previews
|
|
259
|
+
@Preview(name = "Light")
|
|
260
|
+
@Preview(name = "Dark", uiMode = UI_MODE_NIGHT_YES)
|
|
261
|
+
@Composable
|
|
262
|
+
fun UserCardPreviews() {
|
|
263
|
+
UserCard(user = User(1, "Alice"))
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### @PreviewLightDark
|
|
268
|
+
Automatically generates light and dark theme previews.
|
|
269
|
+
|
|
270
|
+
```kotlin
|
|
271
|
+
@PreviewLightDark
|
|
272
|
+
@Composable
|
|
273
|
+
fun UserCardPreview() {
|
|
274
|
+
MyTheme {
|
|
275
|
+
UserCard(user = User(1, "Alice"))
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### @PreviewFontScale
|
|
281
|
+
Shows how composable responds to different font sizes.
|
|
282
|
+
|
|
283
|
+
```kotlin
|
|
284
|
+
@Preview(fontScale = 0.8f, name = "Small Fonts")
|
|
285
|
+
@Preview(fontScale = 1f, name = "Normal Fonts")
|
|
286
|
+
@Preview(fontScale = 1.2f, name = "Large Fonts")
|
|
287
|
+
@Composable
|
|
288
|
+
fun TextPreview() {
|
|
289
|
+
Text("This is text")
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### @PreviewScreenSizes
|
|
294
|
+
Tests multiple screen dimensions.
|
|
295
|
+
|
|
296
|
+
```kotlin
|
|
297
|
+
@Preview(device = Devices.PHONE, name = "Phone")
|
|
298
|
+
@Preview(device = Devices.TABLET, name = "Tablet")
|
|
299
|
+
@Preview(device = Devices.FOLDABLE, name = "Foldable")
|
|
300
|
+
@Composable
|
|
301
|
+
fun ResponsiveLayoutPreview() {
|
|
302
|
+
ResponsiveLayout()
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Source: `androidx.compose.ui.tooling.preview`
|
|
307
|
+
|
|
308
|
+
## CompositionLocal
|
|
309
|
+
|
|
310
|
+
Provide implicit parameters without threading them through the hierarchy.
|
|
311
|
+
|
|
312
|
+
### When to Use
|
|
313
|
+
- **Theming:** Pass `Colors`, `Typography` implicitly
|
|
314
|
+
- **Navigation:** Access from deep in composable tree
|
|
315
|
+
- **Locale/Strings:** Avoid passing through every composable
|
|
316
|
+
|
|
317
|
+
```kotlin
|
|
318
|
+
// ✅ Define at top level
|
|
319
|
+
val LocalUser = staticCompositionLocalOf<User?> { null }
|
|
320
|
+
|
|
321
|
+
@Composable
|
|
322
|
+
fun App(user: User) {
|
|
323
|
+
CompositionLocalProvider(LocalUser provides user) {
|
|
324
|
+
MainContent()
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ✅ Access deep in tree without passing through every composable
|
|
329
|
+
@Composable
|
|
330
|
+
fun UserGreeting() {
|
|
331
|
+
val user = LocalUser.current
|
|
332
|
+
Text("Hello, ${user?.name}")
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### When NOT to Use
|
|
337
|
+
- **Configuration params:** If only 1-2 levels deep, pass directly
|
|
338
|
+
- **Frequently changing values:** Can cause unnecessary recomposition
|
|
339
|
+
- **Dependencies:** Use dependency injection at ViewModel level
|
|
340
|
+
|
|
341
|
+
```kotlin
|
|
342
|
+
// ❌ Over-use: should pass `title` directly
|
|
343
|
+
val LocalTitle = staticCompositionLocalOf<String> { "" }
|
|
344
|
+
|
|
345
|
+
@Composable
|
|
346
|
+
fun Parent() {
|
|
347
|
+
CompositionLocalProvider(LocalTitle provides "My Title") {
|
|
348
|
+
Child()
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ✅ Just pass it
|
|
353
|
+
@Composable
|
|
354
|
+
fun Parent(title: String) {
|
|
355
|
+
Child(title = title)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@Composable
|
|
359
|
+
fun Child(title: String) { ... }
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Types:**
|
|
363
|
+
- `staticCompositionLocalOf`: Value rarely changes, default is a constant
|
|
364
|
+
- `compositionLocalOf`: Value changes frequently, default is computed
|
|
365
|
+
|
|
366
|
+
## Composable Return Values
|
|
367
|
+
|
|
368
|
+
**Never return values from composables.** Use callbacks instead.
|
|
369
|
+
|
|
370
|
+
```kotlin
|
|
371
|
+
// ❌ Wrong: composables don't return values
|
|
372
|
+
@Composable
|
|
373
|
+
fun UserInput(): String {
|
|
374
|
+
var text by remember { mutableStateOf("") }
|
|
375
|
+
return text // Can't do this
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// ✅ Correct: callback pattern
|
|
379
|
+
@Composable
|
|
380
|
+
fun UserInput(onUserInput: (String) -> Unit) {
|
|
381
|
+
var text by remember { mutableStateOf("") }
|
|
382
|
+
TextField(
|
|
383
|
+
value = text,
|
|
384
|
+
onValueChange = {
|
|
385
|
+
text = it
|
|
386
|
+
onUserInput(it) // Notify parent
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Usage
|
|
392
|
+
@Composable
|
|
393
|
+
fun FormScreen() {
|
|
394
|
+
UserInput(onUserInput = { input -> /* handle */ })
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Rationale:** Composables are executed during composition, which happens at unpredictable times and may be skipped or reordered.
|
|
399
|
+
|
|
400
|
+
## Screen-Level Composables
|
|
401
|
+
|
|
402
|
+
Structure screens as a thin ViewModel integration layer above pure composables.
|
|
403
|
+
|
|
404
|
+
### Recommended Pattern
|
|
405
|
+
```kotlin
|
|
406
|
+
// ✅ Screen composable: connects ViewModel
|
|
407
|
+
@Composable
|
|
408
|
+
fun UserDetailsScreen(
|
|
409
|
+
viewModel: UserDetailsViewModel = hiltViewModel(),
|
|
410
|
+
userId: String
|
|
411
|
+
) {
|
|
412
|
+
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
|
413
|
+
LaunchedEffect(userId) {
|
|
414
|
+
viewModel.loadUser(userId)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
UserDetailsContent(
|
|
418
|
+
uiState = uiState,
|
|
419
|
+
onRetry = { viewModel.loadUser(userId) }
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ✅ Content composable: pure (testable, reusable)
|
|
424
|
+
@Composable
|
|
425
|
+
private fun UserDetailsContent(
|
|
426
|
+
uiState: UiState,
|
|
427
|
+
onRetry: () -> Unit
|
|
428
|
+
) {
|
|
429
|
+
when (uiState) {
|
|
430
|
+
is UiState.Loading -> LoadingUI()
|
|
431
|
+
is UiState.Success -> SuccessUI(uiState.user)
|
|
432
|
+
is UiState.Error -> ErrorUI(uiState.message, onRetry)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ✅ Composable for preview/testing
|
|
437
|
+
@Preview
|
|
438
|
+
@Composable
|
|
439
|
+
private fun UserDetailsContentPreview() {
|
|
440
|
+
UserDetailsContent(
|
|
441
|
+
uiState = UiState.Success(User(1, "Alice")),
|
|
442
|
+
onRetry = {}
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Benefits:**
|
|
448
|
+
- Public screen composable integrates ViewModel
|
|
449
|
+
- Private content composable is pure, testable, previewable
|
|
450
|
+
- Clear separation: UI logic (public) vs rendering (private)
|
|
451
|
+
|
|
452
|
+
**Anti-pattern:** Passing ViewModel to child composables. Keep it at screen level only.
|
|
453
|
+
|
|
454
|
+
```kotlin
|
|
455
|
+
// ❌ Couples child to ViewModel
|
|
456
|
+
@Composable
|
|
457
|
+
fun UserCard(viewModel: UserViewModel) {
|
|
458
|
+
val user by viewModel.user.collectAsStateWithLifecycle()
|
|
459
|
+
Text(user.name)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// ✅ Pass only the data
|
|
463
|
+
@Composable
|
|
464
|
+
fun UserCard(user: User) {
|
|
465
|
+
Text(user.name)
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Reusability Guidelines
|
|
470
|
+
|
|
471
|
+
Design composables to be configurable without over-parameterization.
|
|
472
|
+
|
|
473
|
+
### Configuration via Parameters
|
|
474
|
+
```kotlin
|
|
475
|
+
// ✅ Expose what varies, hide what doesn't
|
|
476
|
+
@Composable
|
|
477
|
+
fun Card(
|
|
478
|
+
modifier: Modifier = Modifier,
|
|
479
|
+
content: @Composable () -> Unit
|
|
480
|
+
) {
|
|
481
|
+
// Internal: fixed styling, padding, etc.
|
|
482
|
+
Box(
|
|
483
|
+
modifier = modifier
|
|
484
|
+
.background(Color.White)
|
|
485
|
+
.padding(16.dp)
|
|
486
|
+
.clip(RoundedCornerShape(8.dp))
|
|
487
|
+
) {
|
|
488
|
+
content()
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Avoid Parameter Explosion
|
|
494
|
+
```kotlin
|
|
495
|
+
// ❌ Too many parameters, hard to use
|
|
496
|
+
@Composable
|
|
497
|
+
fun Button(
|
|
498
|
+
text: String,
|
|
499
|
+
textColor: Color,
|
|
500
|
+
backgroundColor: Color,
|
|
501
|
+
cornerRadius: Dp,
|
|
502
|
+
padding: PaddingValues,
|
|
503
|
+
elevation: Dp,
|
|
504
|
+
...
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
// ✅ Sensible defaults, style objects
|
|
508
|
+
@Composable
|
|
509
|
+
fun Button(
|
|
510
|
+
text: String,
|
|
511
|
+
modifier: Modifier = Modifier,
|
|
512
|
+
style: ButtonStyle = ButtonStyle.Primary,
|
|
513
|
+
onClick: () -> Unit
|
|
514
|
+
) { ... }
|
|
515
|
+
|
|
516
|
+
// Or: use Material composables with built-in styles
|
|
517
|
+
@Composable
|
|
518
|
+
fun Button(
|
|
519
|
+
onClick: () -> Unit,
|
|
520
|
+
modifier: Modifier = Modifier,
|
|
521
|
+
enabled: Boolean = true,
|
|
522
|
+
...
|
|
523
|
+
) { ... } // Material3 Button has reasonable defaults
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Common Anti-Patterns
|
|
527
|
+
|
|
528
|
+
### God Composables
|
|
529
|
+
```kotlin
|
|
530
|
+
// ❌ Does too much
|
|
531
|
+
@Composable
|
|
532
|
+
fun Dashboard() {
|
|
533
|
+
// Header
|
|
534
|
+
Box { /* 20 lines */ }
|
|
535
|
+
|
|
536
|
+
// List
|
|
537
|
+
LazyColumn {
|
|
538
|
+
items(items) { /* 15 lines */ }
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Footer
|
|
542
|
+
Box { /* 15 lines */ }
|
|
543
|
+
|
|
544
|
+
// Dialogs, side effects, state management...
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// ✅ Extract and delegate
|
|
548
|
+
@Composable
|
|
549
|
+
fun Dashboard() {
|
|
550
|
+
Column {
|
|
551
|
+
DashboardHeader()
|
|
552
|
+
DashboardContent()
|
|
553
|
+
DashboardFooter()
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Deep Nesting
|
|
559
|
+
```kotlin
|
|
560
|
+
// ❌ Hard to read and debug
|
|
561
|
+
@Composable
|
|
562
|
+
fun LoginScreen() {
|
|
563
|
+
Box { Column { Row { Card { Box { Text { ... } } } } } }
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// ✅ Intermediate variables and extraction
|
|
567
|
+
@Composable
|
|
568
|
+
fun LoginScreen() {
|
|
569
|
+
val form = loginFormState()
|
|
570
|
+
Column {
|
|
571
|
+
LoginForm(form)
|
|
572
|
+
LoginButton(form)
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Passing ViewModel to Children
|
|
578
|
+
```kotlin
|
|
579
|
+
// ❌ Violates composition boundaries
|
|
580
|
+
@Composable
|
|
581
|
+
fun ParentScreen(viewModel: ParentViewModel) {
|
|
582
|
+
ChildCard(viewModel = viewModel) // Don't do this
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// ✅ Extract data, pass to child
|
|
586
|
+
@Composable
|
|
587
|
+
fun ParentScreen(viewModel: ParentViewModel) {
|
|
588
|
+
val data by viewModel.data.collectAsStateWithLifecycle()
|
|
589
|
+
ChildCard(data = data)
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
**Source references:** `androidx.compose.material3`, `androidx.compose.ui.tooling.preview`, `androidx.compose.runtime.CompositionLocal`
|