@shaykec/app-agent 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/.claude/agents/android-customizer.md +9 -1
  2. package/.claude/agents/catalog-analyzer.md +57 -0
  3. package/.claude/agents/ios-customizer.md +9 -1
  4. package/.claude/agents/react-native-customizer.md +71 -0
  5. package/.claude/skills/android-customizer/SKILL.md +108 -23
  6. package/.claude/skills/bug-fixer/SKILL.md +59 -0
  7. package/.claude/skills/catalog-analyzer/SKILL.md +96 -0
  8. package/.claude/skills/customization-planner/SKILL.md +44 -5
  9. package/.claude/skills/design-selector/SKILL.md +3 -1
  10. package/.claude/skills/design-system/SKILL.md +1 -1
  11. package/.claude/skills/exploratory-tester/SKILL.md +82 -0
  12. package/.claude/skills/ios-customizer/SKILL.md +123 -23
  13. package/.claude/skills/module-integrator/SKILL.md +1 -1
  14. package/.claude/skills/react-native-customizer/SKILL.md +97 -11
  15. package/.claude/skills/test-planner/SKILL.md +72 -0
  16. package/.cursor/agents/README.md +3 -1
  17. package/.cursor/agents/android-customizer.md +15 -11
  18. package/.cursor/agents/catalog-analyzer.md +83 -0
  19. package/.cursor/agents/ios-customizer.md +15 -10
  20. package/.cursor/agents/react-native-customizer.md +170 -0
  21. package/.cursor/mcp.json +2 -10
  22. package/.cursor/rules/safety-guardrails.mdc +1 -1
  23. package/.cursor/rules/workflow.mdc +52 -18
  24. package/.cursor/skills/android-customizer/SKILL.md +46 -22
  25. package/.cursor/skills/bug-fixer/SKILL.md +189 -0
  26. package/.cursor/skills/catalog-analyzer/SKILL.md +222 -0
  27. package/.cursor/skills/customization-planner/SKILL.md +55 -8
  28. package/.cursor/skills/design-selector/SKILL.md +6 -5
  29. package/.cursor/skills/design-system/SKILL.md +8 -7
  30. package/.cursor/skills/exploratory-tester/SKILL.md +223 -0
  31. package/.cursor/skills/ios-customizer/SKILL.md +50 -15
  32. package/.cursor/skills/module-integrator/SKILL.md +2 -2
  33. package/.cursor/skills/output-validator/SKILL.md +1 -1
  34. package/.cursor/skills/react-native-customizer/SKILL.md +115 -25
  35. package/.cursor/skills/test-planner/SKILL.md +199 -0
  36. package/AGENTS.md +32 -11
  37. package/CLAUDE.md +78 -33
  38. package/README.md +77 -11
  39. package/designs/DESIGN_CATALOG.md +17 -15
  40. package/designs/DESIGN_PRINCIPLES.md +53 -0
  41. package/designs/brands/accessible-high-contrast.md +14 -0
  42. package/designs/brands/corporate-professional.md +14 -0
  43. package/designs/brands/dark-luxe.md +14 -0
  44. package/designs/brands/kids-playful.md +14 -0
  45. package/designs/brands/medical-clinical.md +14 -0
  46. package/designs/brands/modern-minimal.md +14 -0
  47. package/designs/brands/nature-organic.md +14 -0
  48. package/designs/brands/neo-brutalist.md +14 -0
  49. package/designs/brands/retro-vintage.md +14 -0
  50. package/designs/brands/soft-gradient.md +14 -0
  51. package/designs/brands/sport-athletic.md +14 -0
  52. package/designs/brands/tech-dynamic.md +14 -0
  53. package/designs/brands/vibrant-playful.md +14 -0
  54. package/dist/cli.d.ts +4 -2
  55. package/dist/cli.d.ts.map +1 -1
  56. package/dist/cli.js +91 -1
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config.d.ts +2 -0
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +2 -0
  61. package/dist/config.js.map +1 -1
  62. package/dist/engines/claude-engine.d.ts.map +1 -1
  63. package/dist/engines/claude-engine.js +16 -4
  64. package/dist/engines/claude-engine.js.map +1 -1
  65. package/dist/engines/types.d.ts +1 -1
  66. package/dist/engines/types.d.ts.map +1 -1
  67. package/dist/engines/types.js +31 -2
  68. package/dist/engines/types.js.map +1 -1
  69. package/dist/github.d.ts +3 -0
  70. package/dist/github.d.ts.map +1 -1
  71. package/dist/github.js +47 -4
  72. package/dist/github.js.map +1 -1
  73. package/dist/index.js +217 -9
  74. package/dist/index.js.map +1 -1
  75. package/dist/prompt-builder.d.ts +11 -1
  76. package/dist/prompt-builder.d.ts.map +1 -1
  77. package/dist/prompt-builder.js +216 -1
  78. package/dist/prompt-builder.js.map +1 -1
  79. package/dist/validator.d.ts +7 -2
  80. package/dist/validator.d.ts.map +1 -1
  81. package/dist/validator.js +61 -41
  82. package/dist/validator.js.map +1 -1
  83. package/dist/workspace.js +2 -2
  84. package/dist/workspace.js.map +1 -1
  85. package/package.json +2 -2
  86. package/prompts/agent-prompt.md +35 -18
  87. package/prompts/deep-test-agent-prompt.md +122 -0
  88. package/prompts/fix-agent-prompt.md +90 -0
  89. package/prompts/quick-agent-prompt.md +32 -2
  90. package/prompts/scratch-agent-prompt.md +5 -8
  91. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  92. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  93. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +1 -1
  94. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  95. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/navigation/MainScreen.kt +1 -0
  96. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  97. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/navigation/MainNavigation.kt +5 -1
  98. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  99. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  100. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/MotionPreferencesScreen.kt +3 -3
  101. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/navigation/Navigation.kt +1 -1
  102. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/settings/SettingsScreen.kt +1 -1
  103. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  104. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  105. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  106. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  107. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/settings/SettingsScreen.kt +3 -2
  108. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  109. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/features/settings/SettingsScreen.kt +1 -1
  110. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  111. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/cart/CartScreen.kt +3 -2
  112. package/templates/android/Skeleton/TESTING_MANIFEST.md +2 -1
  113. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/MainActivity.kt +23 -2
  114. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  115. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/theme/AppearanceManager.kt +42 -0
  116. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/profile/ProfileScreen.kt +20 -8
  117. package/templates/android/Skeleton/tests/03_detail_screen.yaml +3 -2
  118. package/templates/android/Skeleton/tests/04_favorites.yaml +3 -2
  119. package/templates/android/Skeleton/tests/08_full_e2e.yaml +9 -2
  120. package/templates/android/Skeleton/tests/09_dark_mode.yaml +50 -0
  121. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  122. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  123. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/settings/SettingsScreen.kt +3 -2
  124. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  125. package/templates/ios/BookTemplate/BookTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  126. package/templates/ios/ChatTemplate/ChatTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  127. package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +1 -0
  128. package/templates/ios/DashTemplate/DashTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  129. package/templates/ios/DashTemplate/DashTemplate/Core/Strings.swift +13 -0
  130. package/templates/ios/DashTemplate/DashTemplate.xcodeproj/project.pbxproj +32 -20
  131. package/templates/ios/FamilyTemplate/FamilyTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  132. package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  133. package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Strings.swift +42 -0
  134. package/templates/ios/FinanceTemplate/FinanceTemplate.xcodeproj/project.pbxproj +36 -30
  135. package/templates/ios/GameTemplate/GameTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  136. package/templates/ios/HealthTemplate/HealthTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  137. package/templates/ios/LearnTemplate/LearnTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  138. package/templates/ios/MapTemplate/MapTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  139. package/templates/ios/MediaTemplate/MediaTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  140. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  141. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Strings.swift +12 -0
  142. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Features/SkeletonLoading/SkeletonLoadingView.swift +2 -37
  143. package/templates/ios/ShopTemplate/ShopTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  144. package/templates/ios/Skeleton/Skeleton/Core/Animation/AnimatedTransitionsView.swift +201 -0
  145. package/templates/ios/Skeleton/tests/08_full_e2e.yaml +4 -0
  146. package/templates/ios/Skeleton/tests/09_dark_mode.yaml +52 -0
  147. package/templates/ios/SocialTemplate/SocialTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  148. package/templates/ios/TaskTemplate/TaskTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  149. package/templates/ios/TrackTemplate/TrackTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  150. package/templates/react-native/BookTemplate/src/animation/useAnimatedList.ts +219 -2
  151. package/templates/react-native/BookTemplate/src/animation/useMotionPreferences.ts +23 -9
  152. package/templates/react-native/BookTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  153. package/templates/react-native/ChatTemplate/src/animation/useAnimatedList.ts +219 -2
  154. package/templates/react-native/ChatTemplate/src/animation/useMotionPreferences.ts +23 -9
  155. package/templates/react-native/ChatTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  156. package/templates/react-native/DashTemplate/src/animation/useAnimatedList.ts +219 -2
  157. package/templates/react-native/DashTemplate/src/animation/useMotionPreferences.ts +23 -9
  158. package/templates/react-native/DashTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  159. package/templates/react-native/FamilyTemplate/src/animation/useAnimatedList.ts +219 -2
  160. package/templates/react-native/FamilyTemplate/src/animation/useMotionPreferences.ts +23 -9
  161. package/templates/react-native/FamilyTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  162. package/templates/react-native/FinanceTemplate/src/animation/useAnimatedList.ts +219 -2
  163. package/templates/react-native/FinanceTemplate/src/animation/useMotionPreferences.ts +23 -9
  164. package/templates/react-native/FinanceTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  165. package/templates/react-native/GameTemplate/src/animation/useAnimatedList.ts +219 -2
  166. package/templates/react-native/GameTemplate/src/animation/useMotionPreferences.ts +23 -9
  167. package/templates/react-native/GameTemplate/src/screens/GameDetail/GameDetailScreen.tsx +2 -1
  168. package/templates/react-native/GameTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  169. package/templates/react-native/HealthTemplate/src/animation/useAnimatedList.ts +219 -2
  170. package/templates/react-native/HealthTemplate/src/animation/useMotionPreferences.ts +23 -9
  171. package/templates/react-native/HealthTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  172. package/templates/react-native/HealthTemplate/src/screens/WorkoutDetail/WorkoutDetailScreen.tsx +1 -1
  173. package/templates/react-native/LearnTemplate/src/animation/useAnimatedList.ts +219 -2
  174. package/templates/react-native/LearnTemplate/src/animation/useMotionPreferences.ts +23 -9
  175. package/templates/react-native/LearnTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  176. package/templates/react-native/MapTemplate/src/animation/useAnimatedList.ts +219 -2
  177. package/templates/react-native/MapTemplate/src/animation/useMotionPreferences.ts +23 -9
  178. package/templates/react-native/MapTemplate/src/screens/Map/MapScreen.tsx +14 -0
  179. package/templates/react-native/MapTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  180. package/templates/react-native/MediaTemplate/src/animation/useAnimatedList.ts +219 -2
  181. package/templates/react-native/MediaTemplate/src/animation/useMotionPreferences.ts +23 -9
  182. package/templates/react-native/MediaTemplate/src/screens/PlaylistDetail/PlaylistDetailScreen.tsx +1 -1
  183. package/templates/react-native/MediaTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  184. package/templates/react-native/ReferenceTemplate/src/animation/useAnimatedList.ts +219 -2
  185. package/templates/react-native/ReferenceTemplate/src/animation/useMotionPreferences.ts +23 -9
  186. package/templates/react-native/ReferenceTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
  187. package/templates/react-native/ShopTemplate/src/animation/useAnimatedList.ts +219 -2
  188. package/templates/react-native/ShopTemplate/src/animation/useMotionPreferences.ts +23 -9
  189. package/templates/react-native/ShopTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  190. package/templates/react-native/Skeleton/TESTING_MANIFEST.md +2 -1
  191. package/templates/react-native/Skeleton/src/animation/useAnimatedList.ts +219 -2
  192. package/templates/react-native/Skeleton/src/animation/useMotionPreferences.ts +23 -9
  193. package/templates/react-native/Skeleton/src/screens/Profile/ProfileScreen.tsx +1 -1
  194. package/templates/react-native/Skeleton/tests/07_profile.yaml +3 -2
  195. package/templates/react-native/Skeleton/tests/08_full_e2e.yaml +12 -1
  196. package/templates/react-native/Skeleton/tests/09_dark_mode.yaml +46 -0
  197. package/templates/react-native/SocialTemplate/src/animation/useAnimatedList.ts +219 -2
  198. package/templates/react-native/SocialTemplate/src/animation/useMotionPreferences.ts +23 -9
  199. package/templates/react-native/SocialTemplate/src/screens/Feed/FeedScreen.tsx +1 -0
  200. package/templates/react-native/SocialTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  201. package/templates/react-native/TaskTemplate/src/animation/useAnimatedList.ts +219 -2
  202. package/templates/react-native/TaskTemplate/src/animation/useMotionPreferences.ts +23 -9
  203. package/templates/react-native/TaskTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  204. package/templates/react-native/TrackTemplate/src/animation/useAnimatedList.ts +219 -2
  205. package/templates/react-native/TrackTemplate/src/animation/useMotionPreferences.ts +23 -9
  206. package/templates/react-native/TrackTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
  207. package/templates/shared/ios/AnimatedTransitions/AnimatedTransitionsView.swift +233 -93
  208. package/.claude/agents/template-selector.md +0 -39
  209. package/.claude/skills/module-selector/SKILL.md +0 -81
  210. package/.claude/skills/template-selector/SKILL.md +0 -44
  211. package/.cursor/agents/template-selector.md +0 -52
  212. package/.cursor/skills/module-selector/SKILL.md +0 -135
  213. package/.cursor/skills/template-selector/SKILL.md +0 -123
@@ -13,9 +13,8 @@ You have specialised skills available in `.cursor/skills/`. Each skill contains
13
13
  | Step | Skill | Purpose |
14
14
  |------|-------|---------|
15
15
  | 0 | `prompt-validator` | Validate user prompt for injection/malicious intent |
16
- | 0 | `template-selector` | Select the best app template from CATALOG.md |
16
+ | 0 | `catalog-analyzer` | Select the best template from CATALOG.md AND shared modules from MODULES_CATALOG.md |
17
17
  | 0 | `design-selector` | Select the best design brand from DESIGN_CATALOG.md |
18
- | 0 | `module-selector` | Select shared modules from MODULES_CATALOG.md based on app keywords |
19
18
  | 4 | `module-integrator` | Read shared module references and write adapted code into the app |
20
19
  | 2 | `app-renaming` | Rename app consistently across all files |
21
20
  | 3 | `customization-planner` | Produce a manifest with design brief, content brief, per-screen changes, and parallel batches |
@@ -37,8 +36,7 @@ Every skill writes a report file to `output/{app-name}/reports/`. These reports
37
36
  ```
38
37
  output/{app-name}/reports/
39
38
  01-prompt-validation.md
40
- 02-template-selection.md
41
- 02b-module-selection.md
39
+ 02-catalog-analysis.md
42
40
  03-design-brand.md
43
41
  customization-manifest.md
44
42
  04-content-brief.md
@@ -69,26 +67,46 @@ Wait for all parallel tasks to complete before proceeding to the next step.
69
67
 
70
68
  | Group | Steps | Why They're Independent |
71
69
  |-------|-------|------------------------|
72
- | A | 0 (Prompt Validation) + 0 (Template Selection) + 0 (Design Brand Selection) + 0 (Module Selection) | All are read-only analysis of the user description against catalogs |
70
+ | A | 0 (Prompt Validation) + 0 (Catalog Analysis) + 0 (Design Brand Selection) | All are read-only analysis of the user description against catalogs |
73
71
  | B | Screen customization batches (from planner) | Each subagent edits only its assigned screen files |
74
- | C | 10 (Security Audit) + 11 (Output Validation) | Both are read-only scans of the generated code |
72
+ | C | 7 (Security Audit) + 7 (Output Validation) + 7 (Boot Sims) | Read-only scans + independent sim boot |
75
73
  | D | Interactive testing batches (from planner) | Each subagent tests its screens on its own simulator |
76
74
  | E | Maestro test batches (from planner) | Each subagent runs YAML tests on its own simulator |
77
75
 
76
+ ## Design Quality Standards
77
+
78
+ Generated apps must NOT look like generic templates. Every app should feel handcrafted and alive. When applying the Visual Polish Plan from the manifest:
79
+
80
+ These modifiers are built into every template and always available (no module dependency):
81
+
82
+ - **Shadows**: Every card and elevated surface MUST have shadows. iOS: `.cardShadow()`. Android: `Modifier.cardShadow()`. RN: `cardShadowStyle()`. Prefer colored shadows (primary-tinted) over neutral gray.
83
+ - **Gradients**: Hero sections and primary CTAs SHOULD use gradient backgrounds from the design brief. iOS: `LinearGradient`. Android: `Brush.linearGradient`. RN: `LinearGradient` component.
84
+ - **Press feedback**: All tappable elements MUST have visual press feedback. iOS: `.scaleOnPress()`. Android: `Modifier.scaleOnPress()`. RN: `useScaleOnPress()` hook. Add haptic on key interactions (favorite toggle, submit).
85
+ - **Staggered animations**: List items MUST animate in with staggered entrance. iOS: `.staggeredAppear(index:)`. Android: `Modifier.staggeredAppear(index)`. RN: `useStaggeredAppear(index)` hook. This applies to every screen with a scrollable list.
86
+ - **Empty states**: Empty states MUST be visually engaging — use a gradient circle background behind the icon, add an animated entrance (iOS: `.slideIn()`, Android: `Modifier.slideIn()`, RN: `useSlideIn()`), and ensure the composition feels polished, not just "icon + text".
87
+ - **Glass/blur**: Sheets and overlays SHOULD use glass/blur backgrounds (`.ultraThinMaterial` on iOS, tonal elevation on Android, blur overlay on React Native).
88
+ - **Shimmer loading**: Loading/placeholder states SHOULD use shimmer animation instead of plain gray rectangles. iOS: `.shimmer()`. Android: `Modifier.shimmer()`. RN: `useShimmer()` hook. Apply to skeleton views while data is loading.
89
+ - **Pulse**: Live indicators, notification badges, and "recording" states SHOULD use repeating pulse animation. iOS: `.pulse()`. Android: `Modifier.pulse()`. RN: `usePulse()` hook.
90
+ - **Heart bounce**: Favorite/like toggle buttons SHOULD use bounce-on-activate animation. iOS: `.heartBounce(isActive:)`. Android: `Modifier.heartBounce(isActive)`. RN: `useHeartBounce(isActive)` hook. Gives satisfying feedback on favorite toggles.
91
+ - **Visual depth**: The app should have clear visual hierarchy through shadows, elevation, and layering. Hero elements stand out above section headers, which stand out above cards.
92
+ - **Motion**: The app should feel alive — elements respond to touch (press feedback), scroll (parallax, staggered), and state changes (bounces, fades). Respect system Reduce Motion preferences.
93
+ - **Brand motion tokens**: Read the selected brand's `## Motion & Effects` section for per-brand spring preset, press scale, shadow style, gradient usage, depth approach, and haptic policy. Follow these specs when applying visual polish.
94
+
95
+ IMPORTANT: These modifiers are defined in the template's animation utilities. Do NOT invent new modifier names. Use exactly the names listed above.
96
+
78
97
  ## Your Workflow
79
98
 
80
99
  Follow these steps in order. Steps marked `[PARALLEL]` should use `Task` for concurrent execution.
81
100
 
82
101
  ### Step 0 — [PARALLEL] Analysis Phase
83
102
 
84
- Dispatch four `Task` subagents concurrently:
103
+ Dispatch three `Task` subagents concurrently:
85
104
 
86
105
  1. **Prompt Validation** — follow `prompt-validator` skill. Validate the user description.
87
- 2. **Template Selection** — follow `template-selector` skill. Read `templates/CATALOG.md` and select the best template.
106
+ 2. **Catalog Analysis** — follow `catalog-analyzer` skill. Read `templates/CATALOG.md` to select the best template, then read `templates/shared/MODULES_CATALOG.md` to select shared modules (using the selected template for improved accuracy via "Relevant Templates" column).
88
107
  3. **Design Brand Selection** — follow `design-selector` skill. Read `designs/DESIGN_CATALOG.md` and select the best brand.
89
- 4. **Module Selection** — follow `module-selector` skill. Read `templates/shared/MODULES_CATALOG.md` and select which shared modules to include. Select modules whose keywords match the user's description — no modules are auto-included.
90
108
 
91
- Wait for all four. If prompt validation FAILS: stop immediately.
109
+ Wait for all three. If prompt validation FAILS: stop immediately.
92
110
 
93
111
  This step also creates the `reports/` directory and initializes `summary.json`.
94
112
 
@@ -154,18 +172,15 @@ Follow the `build-tester` skill. Compile the app and locate the build artifact p
154
172
 
155
173
  If the build fails, fix the errors and rebuild until it succeeds.
156
174
 
157
- **Save the build artifact path — you need it for Step 9.**
175
+ **Save the build artifact path — you need it for Step 8.**
158
176
 
159
- ### Step 7 — [PARALLEL] Post-build audits
177
+ ### Step 7 — [PARALLEL] Post-build audits + boot simulators
160
178
 
161
- Dispatch two `Task` subagents concurrently:
179
+ Dispatch three concurrent tasks (sim boot is independent of audits, saves ~30-60s):
162
180
 
163
181
  1. **Security Audit** — follow `code-auditor` skill
164
182
  2. **Output Validation** — follow `output-validator` skill
165
-
166
- ### Step 8 — Boot simulators for testing
167
-
168
- Boot 2-3 simulators for parallel interactive testing and Maestro execution. Use ai-tester MCP `device` tool:
183
+ 3. **Boot simulators** — boot 2-3 simulators using ai-tester MCP `device` tool:
169
184
  ```
170
185
  device({ action: "list", platform: "ios" }) // or "android"
171
186
  device({ action: "boot", platform: "ios", deviceId: "{sim1}" })
@@ -173,7 +188,9 @@ device({ action: "boot", platform: "ios", deviceId: "{sim2}" })
173
188
  device({ action: "boot", platform: "ios", deviceId: "{sim3}" })
174
189
  ```
175
190
 
176
- Install the build artifact on all booted simulators:
191
+ ### Step 8 Install app on simulators
192
+
193
+ Install the build artifact on all (already booted) simulators:
177
194
  ```
178
195
  device({ action: "install", platform: "ios", appPath: "{artifact_path}" })
179
196
  ```
@@ -0,0 +1,122 @@
1
+ You are AppAgent in **Deep Testing mode**. An app has already been built and you need to perform comprehensive testing using a 4-phase pipeline: test plan generation, exploratory testing, structured testing, and optionally auto-fixing bugs.
2
+
3
+ ## App Context
4
+
5
+ **App name:** {{appName}}
6
+ **Platform:** {{platformLabel}}
7
+ **Bundle ID:** {{bundleId}}
8
+ **App directory:** {{appDir}}
9
+ {{artifactSection}}
10
+
11
+ ## Skills
12
+
13
+ You have specialised skills available in `.cursor/skills/`. Read the `SKILL.md` file and follow its instructions.
14
+
15
+ | Skill | Purpose |
16
+ |-------|---------|
17
+ | `test-planner` | **Phase 1** — Analyze code and produce a structured test plan |
18
+ | `exploratory-tester` | **Phase 2** — Screenshot + accessibility-tree driven exploratory testing |
19
+ | `ui-tester` | **Phase 3** — Structured interactive testing following the test plan |
20
+ | `bug-fixer` | **Phase 4** — Fix bugs from the bug report (only if fix mode is enabled) |
21
+ | `build-tester` | Compile the app (only if rebuild is needed) |
22
+
23
+ ## Report Files
24
+
25
+ Write reports to `{{appDir}}/reports/`. Update the existing `summary.json` — read it, append your step entries, and write it back.
26
+
27
+ Reports to write:
28
+ - `10-test-plan.md` — Structured test plan from code analysis (Phase 1)
29
+ - `11-bug-report.md` — Merged bug report from exploratory + structured testing (Phases 2+3)
30
+ {{fixReportLine}}
31
+ - Update `summary.json` with step entries for each phase. When done, set `overallResult`, `filesWritten`, and `duration`.
32
+
33
+ ## Parallel Execution
34
+
35
+ Use the `Task` tool to run independent steps concurrently.
36
+
37
+ | Group | Steps | Why They're Independent |
38
+ |-------|-------|------------------------|
39
+ | A | Exploratory + structured testing | Each runs on its own simulator, different approaches |
40
+
41
+ ## Your Workflow
42
+
43
+ ### Phase 1 — Test Plan Generation (offline)
44
+
45
+ Follow the `test-planner` skill. Read the app's source code and produce a structured test plan at `{{appDir}}/reports/10-test-plan.md`.
46
+
47
+ This phase does NOT require a simulator. Analyze:
48
+ - `TESTING_MANIFEST.md` — all test IDs and element inventory
49
+ - `AppConfig` — feature flags and configuration
50
+ - `MockDataProvider` — data structure and counts
51
+ - All View and ViewModel files — interactive elements, navigation, state logic
52
+ - `customization-manifest.md` (if exists) — screen descriptions
53
+ - `requirements.md` or `PRD.md` (if exists) — business requirements
54
+
55
+ The test plan should include: app overview, per-screen test matrix with checkboxes, edge cases, regression checks, and priority assignments (P0-P3).
56
+
57
+ ### Phase 2+3 — Boot Simulators and Test in Parallel
58
+
59
+ Boot 2-3 simulators for parallel testing:
60
+ ```
61
+ device({ action: "list", platform: "{{platform}}" })
62
+ device({ action: "boot", platform: "{{platform}}", deviceId: "{sim1}" })
63
+ device({ action: "boot", platform: "{{platform}}", deviceId: "{sim2}" })
64
+ ```
65
+
66
+ Install the build artifact on all booted simulators:
67
+ ```
68
+ device({ action: "install", platform: "{{platform}}", appPath: "{artifact_path}" })
69
+ ```
70
+
71
+ Then dispatch **two parallel `Task` subagents**:
72
+
73
+ #### Subagent A — Exploratory Testing (Simulator 1)
74
+
75
+ - Follows the `exploratory-tester` skill
76
+ - Does NOT read source code — only uses screenshots + accessibility tree from `inspect()`
77
+ - Explores every screen freely, tapping every element, checking for visual/a11y/UX/content issues
78
+ - Discovers bugs that the structured test plan might miss
79
+ - Writes findings to `{{appDir}}/reports/11-bug-report.md` with `[EXPLORATORY]` tags
80
+
81
+ #### Subagent B — Structured Testing (Simulator 2)
82
+
83
+ - Uses the test plan from Phase 1 (`{{appDir}}/reports/10-test-plan.md`)
84
+ - Follows the per-screen test matrix systematically
85
+ - Marks each test case as PASS or FAIL
86
+ - Updates `10-test-plan.md` with results
87
+ - Appends failures to `{{appDir}}/reports/11-bug-report.md` with `[STRUCTURED]` tags
88
+
89
+ {{testBatchInstructions}}
90
+
91
+ ### Merge Bug Report
92
+
93
+ After both subagents complete, read `{{appDir}}/reports/11-bug-report.md` and ensure it has a unified summary at the top:
94
+
95
+ ```markdown
96
+ # Bug Report
97
+
98
+ ## Summary
99
+ - Total bugs: {N}
100
+ - From exploratory testing: {N}
101
+ - From structured testing: {N}
102
+ - By severity: P0={N}, P1={N}, P2={N}, P3={N}
103
+ - By category: Visual={N}, A11Y={N}, UX={N}, Content={N}, State={N}, Crash={N}
104
+ ```
105
+
106
+ {{fixSection}}
107
+
108
+ ### Cleanup
109
+
110
+ 1. {{simulatorCleanup}}
111
+ 2. Update `summary.json` — set `overallResult` to `PASS` (no bugs) or `BUGS_FOUND` (bugs documented) or `BUGS_FIXED` (bugs fixed). Update `filesWritten` and `duration`.
112
+
113
+ ## Important Rules
114
+
115
+ - ONLY write files under `output/` — NEVER modify `templates/`
116
+ - NEVER modify files under `.cursor/` (agents, rules, skills, hooks)
117
+ - Phase 1 is offline — do NOT boot simulators until Phase 2
118
+ - The exploratory tester must NOT read source code — only screenshots + element tree
119
+ - The structured tester follows the test plan — it does not explore freely
120
+ - Use ai-tester MCP tools for ALL device interaction — not shell commands like `xcrun simctl`
121
+ - Preserve the MVVM architecture when fixing bugs
122
+ - Keep the MockDataProvider pattern when fixing data issues
@@ -0,0 +1,90 @@
1
+ You are AppAgent in **Bug Fix mode**. An app has been deep-tested and a bug report exists. Your job is to fix the documented bugs, rebuild, and verify the fixes.
2
+
3
+ ## App Context
4
+
5
+ **App name:** {{appName}}
6
+ **Platform:** {{platformLabel}}
7
+ **Bundle ID:** {{bundleId}}
8
+ **App directory:** {{appDir}}
9
+ {{artifactSection}}
10
+
11
+ ## Bug Report
12
+
13
+ The bug report is at `{{appDir}}/reports/11-bug-report.md`. Read it to understand all documented bugs.
14
+
15
+ {{bugReportSummary}}
16
+
17
+ ## Skills
18
+
19
+ You have specialised skills available in `.cursor/skills/`. Read the `SKILL.md` file and follow its instructions.
20
+
21
+ | Skill | Purpose |
22
+ |-------|---------|
23
+ | `bug-fixer` | **PRIMARY** — Read bug report and fix bugs systematically |
24
+ | `build-tester` | Compile the app after fixes |
25
+
26
+ ## Report Files
27
+
28
+ Write reports to `{{appDir}}/reports/`. Update the existing `summary.json`.
29
+
30
+ Reports to write:
31
+ - `12-fix-report.md` — Fix details, root causes, files modified, verification results
32
+ - Update `summary.json` with the bug-fix step entry. When done, set `overallResult`, `filesWritten`, and `duration`.
33
+
34
+ ## Your Workflow
35
+
36
+ ### Step 1 — Read and Prioritize
37
+
38
+ Follow the `bug-fixer` skill. Read `{{appDir}}/reports/11-bug-report.md` and triage all bugs:
39
+ - **FIX** — can be fixed in source code
40
+ - **DEFER** — needs major refactoring (document recommendation)
41
+ - **SKIP** — false positive or cosmetic non-issue
42
+
43
+ Sort by priority: P0 (Critical) → P1 (High) → P2 (Medium) → P3 (Low).
44
+
45
+ ### Step 2 — Fix Bugs
46
+
47
+ For each bug marked FIX, in priority order:
48
+ 1. Locate the source file(s)
49
+ 2. Understand the root cause
50
+ 3. Apply the minimal fix
51
+ 4. Document what you changed
52
+
53
+ ### Step 3 — Rebuild
54
+
55
+ After all fixes are applied, rebuild the app using the `build-tester` skill. Maximum 3 rebuild cycles.
56
+
57
+ ### Step 4 — Verify Fixes
58
+
59
+ Boot a simulator, install the rebuilt app, and verify each fix:
60
+ ```
61
+ device({ action: "boot", platform: "{{platform}}", deviceId: "{sim}" })
62
+ device({ action: "install", platform: "{{platform}}", appPath: "{artifact}" })
63
+ inspect({ platform: "{{platform}}", app: "{{bundleId}}", deviceName: "{sim}" })
64
+ ```
65
+
66
+ For each fixed bug: navigate to the affected screen, reproduce the original steps, verify the issue is resolved.
67
+
68
+ ### Step 5 — Write Fix Report
69
+
70
+ Write `{{appDir}}/reports/12-fix-report.md` with:
71
+ - Summary counts (fixed, deferred, skipped)
72
+ - Per-bug details (root cause, fix, files modified, verification)
73
+ - Deferred bugs with recommendations
74
+ - Rebuild and verification results
75
+
76
+ ### Step 6 — Cleanup
77
+
78
+ 1. {{simulatorCleanup}}
79
+ 2. Update `summary.json` — set `overallResult` to `FIXED` or `PARTIAL_FIX`. Update `filesWritten` and `duration`.
80
+
81
+ ## Important Rules
82
+
83
+ - ONLY write files under `output/` — NEVER modify `templates/`
84
+ - NEVER modify files under `.cursor/` (agents, rules, skills, hooks)
85
+ - Fix in priority order — P0 first
86
+ - Minimal changes — don't refactor unrelated code
87
+ - Preserve MVVM architecture and MockDataProvider pattern
88
+ - Maximum 3 rebuild cycles
89
+ - Do NOT add new external dependencies — DEFER bugs that require them
90
+ - Use ai-tester MCP tools for ALL device interaction
@@ -79,6 +79,30 @@ Follow the `build-tester` skill. Compile the app and fix any errors.
79
79
  - For Android: use `./gradlew assembleDebug`
80
80
  - For React Native: use `npx react-native run-ios` or `npx react-native run-android`
81
81
 
82
+ After a successful build, write a minimal summary to `{{appDir}}/reports/summary.json`:
83
+
84
+ ```json
85
+ {
86
+ "appName": "{{appName}}",
87
+ "platform": "{{platform}}",
88
+ "bundleId": "{{bundleId}}",
89
+ "mode": "quick",
90
+ "steps": [
91
+ {
92
+ "step": 6,
93
+ "name": "build",
94
+ "result": "SUCCESS",
95
+ "artifactPath": "{FULL path to the .app or .apk build artifact}"
96
+ }
97
+ ],
98
+ "overallResult": "PASS",
99
+ "filesWritten": 0,
100
+ "duration": ""
101
+ }
102
+ ```
103
+
104
+ Create the `reports/` directory first. Set `artifactPath` to the actual build artifact location. Set `overallResult` to `"PASS"` if the build succeeded, `"FAIL"` if not. No markdown report files are needed — just this JSON.
105
+
82
106
  ### Step 7 — Smoke test
83
107
 
84
108
  Boot 1 simulator/emulator, install the app, and verify:
@@ -87,7 +111,13 @@ Boot 1 simulator/emulator, install the app, and verify:
87
111
  - Tapping an item navigates to the detail screen
88
112
  - The create flow opens correctly
89
113
 
90
- Use the `ai-tester` MCP tools for device interaction.
114
+ Use the `ai-tester` MCP tools for device interaction:
115
+ 1. Use `device({ action: "list" })` to find or boot a simulator
116
+ 2. Install the app using the build artifact from Step 6
117
+ 3. Use `inspect()` to verify each tab renders
118
+
119
+ **IMPORTANT:** If ai-tester MCP tools fail or Appium is unavailable, retry once. If still failing, note the failure explicitly in `summary.json` by setting `overallResult` to `"PASS_NO_SMOKE_TEST"` and add a `"smokeTest"` field with `"result": "SKIPPED"` and `"reason": "{why it failed}"`. Do NOT silently skip the smoke test.
120
+
91
121
  No Maestro tests needed in quick mode.
92
122
 
93
123
  ### Step 8 — Screenshot Collection
@@ -116,7 +146,7 @@ Read `.cursor/skills/build-tester/SKILL.md` (or `.claude/skills/build-tester/SKI
116
146
 
117
147
  - ONLY modify files under `{{appDir}}/`
118
148
  - Do NOT read CATALOG.md, DESIGN_CATALOG.md, or MODULES_CATALOG.md
119
- - Do NOT generate a customization manifest or reports
149
+ - Do NOT generate a customization manifest or markdown report files (only write `reports/summary.json`)
120
150
  - Do NOT dispatch subagents — work inline
121
151
  - Do NOT integrate shared modules
122
152
  - Do NOT run security audits or output validation
@@ -22,9 +22,8 @@ You have specialised skills available in `.cursor/skills/`. Each skill contains
22
22
  | Step | Skill | Purpose |
23
23
  |------|-------|---------|
24
24
  | 0 | `prompt-validator` | Validate user prompt for injection/malicious intent |
25
- | 0 | `template-selector` | Select 1-3 reference templates from CATALOG.md (read for patterns, do NOT clone) |
25
+ | 0 | `catalog-analyzer` | Select 1-3 reference templates from CATALOG.md (read for patterns, do NOT clone) AND shared modules from MODULES_CATALOG.md |
26
26
  | 0 | `design-selector` | Select the best design brand from DESIGN_CATALOG.md |
27
- | 0 | `module-selector` | Select shared modules from MODULES_CATALOG.md based on app keywords |
28
27
  | 1 | `content-writer` | Generate all user-facing strings (used during architecture + content planning) |
29
28
  | 3 | `module-integrator` | Read shared module references and write adapted code into the app |
30
29
  | 4 | `design-system` | Apply the selected brand's tokens to the app |
@@ -41,8 +40,7 @@ Every skill writes a report file to `output/{app-name}/reports/`. These reports
41
40
  ```
42
41
  output/{app-name}/reports/
43
42
  01-prompt-validation.md
44
- 02-template-selection.md
45
- 02b-module-selection.md
43
+ 02-catalog-analysis.md
46
44
  03-design-brand.md
47
45
  architecture-plan.md
48
46
  04-content-brief.md
@@ -83,14 +81,13 @@ Follow these steps in order. Steps marked `[PARALLEL]` should use `Task` for con
83
81
 
84
82
  ### Step 0 — [PARALLEL] Analysis Phase
85
83
 
86
- Dispatch four `Task` subagents concurrently:
84
+ Dispatch three `Task` subagents concurrently:
87
85
 
88
86
  1. **Prompt Validation** — follow `prompt-validator` skill. Validate the user description.
89
- 2. **Reference Template Selection** — follow `template-selector` skill. Read `templates/CATALOG.md` and select 1-3 reference templates. These are NOT cloned — they are read for architectural patterns (MVVM structure, navigation patterns, mock data format, theming approach). For hybrid apps, select multiple templates that cover different aspects of the app.
87
+ 2. **Catalog Analysis** — follow `catalog-analyzer` skill. Read `templates/CATALOG.md` to select 1-3 reference templates (NOT cloned — read for architectural patterns: MVVM structure, navigation patterns, mock data format, theming approach). Then read `templates/shared/MODULES_CATALOG.md` to select shared modules using template context. For hybrid apps, select multiple templates that cover different aspects of the app. **The module list feeds directly into Step 1 (architecture planning).**
90
88
  3. **Design Brand Selection** — follow `design-selector` skill. Read `designs/DESIGN_CATALOG.md` and select the best brand.
91
- 4. **Module Selection** — follow `module-selector` skill. Read `templates/shared/MODULES_CATALOG.md` and select which shared modules to include. Select modules whose keywords match the user's description — no modules are auto-included. **The output of this step feeds directly into Step 1 (architecture planning).**
92
89
 
93
- Wait for all four. If prompt validation FAILS: stop immediately.
90
+ Wait for all three. If prompt validation FAILS: stop immediately.
94
91
 
95
92
  This step also creates the `reports/` directory and initializes `summary.json` with `mode: "scratch"`.
96
93
 
@@ -1,14 +1,24 @@
1
1
  package com.appship.book.core.animation
2
2
 
3
+ import android.view.HapticFeedbackConstants
3
4
  import androidx.compose.animation.*
4
5
  import androidx.compose.animation.core.*
6
+ import androidx.compose.foundation.clickable
7
+ import androidx.compose.foundation.gestures.detectTapGestures
8
+ import androidx.compose.foundation.interaction.MutableInteractionSource
9
+ import androidx.compose.foundation.interaction.collectIsPressedAsState
5
10
  import androidx.compose.foundation.layout.offset
6
11
  import androidx.compose.runtime.*
7
12
  import androidx.compose.ui.Modifier
8
13
  import androidx.compose.ui.composed
9
14
  import androidx.compose.ui.draw.alpha
10
15
  import androidx.compose.ui.draw.scale
16
+ import androidx.compose.ui.draw.shadow
17
+ import androidx.compose.ui.graphics.Color
18
+ import androidx.compose.ui.input.pointer.pointerInput
19
+ import androidx.compose.ui.platform.LocalView
11
20
  import androidx.compose.ui.unit.IntOffset
21
+ import androidx.compose.ui.unit.dp
12
22
 
13
23
  /**
14
24
  * Staggered appear animation for list items.
@@ -118,3 +128,181 @@ fun Modifier.bounceOnChange(
118
128
 
119
129
  this.scale(bounceAnim)
120
130
  }
131
+
132
+ /**
133
+ * Scale-down press feedback for tappable elements.
134
+ * Scales to 0.95 on press with spring return animation.
135
+ */
136
+ fun Modifier.scaleOnPress(): Modifier = composed {
137
+ val interactionSource = remember { MutableInteractionSource() }
138
+ val isPressed by interactionSource.collectIsPressedAsState()
139
+
140
+ val scale by animateFloatAsState(
141
+ targetValue = if (isPressed) 0.95f else 1f,
142
+ animationSpec = spring(
143
+ dampingRatio = Spring.DampingRatioMediumBouncy,
144
+ stiffness = Spring.StiffnessMedium
145
+ ),
146
+ label = "pressScale"
147
+ )
148
+
149
+ this
150
+ .scale(scale)
151
+ .clickable(
152
+ interactionSource = interactionSource,
153
+ indication = null
154
+ ) { }
155
+ }
156
+
157
+ /**
158
+ * Triggers haptic feedback on tap.
159
+ */
160
+ fun Modifier.hapticFeedback(): Modifier = composed {
161
+ val view = LocalView.current
162
+ this.pointerInput(Unit) {
163
+ detectTapGestures {
164
+ view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Slide-from-side + fade-in animation on appear.
171
+ */
172
+ fun Modifier.slideAndFade(
173
+ delayMs: Int = 0,
174
+ durationMs: Int = 400
175
+ ): Modifier = composed {
176
+ var isVisible by remember { mutableStateOf(false) }
177
+
178
+ val alpha by animateFloatAsState(
179
+ targetValue = if (isVisible) 1f else 0f,
180
+ animationSpec = tween(
181
+ durationMillis = durationMs,
182
+ delayMillis = delayMs,
183
+ easing = FastOutSlowInEasing
184
+ ),
185
+ label = "slideAndFadeAlpha"
186
+ )
187
+
188
+ val offsetX by animateIntAsState(
189
+ targetValue = if (isVisible) 0 else 40,
190
+ animationSpec = tween(
191
+ durationMillis = durationMs,
192
+ delayMillis = delayMs,
193
+ easing = FastOutSlowInEasing
194
+ ),
195
+ label = "slideAndFadeOffsetX"
196
+ )
197
+
198
+ LaunchedEffect(Unit) {
199
+ isVisible = true
200
+ }
201
+
202
+ this
203
+ .alpha(alpha)
204
+ .offset { IntOffset(offsetX, 0) }
205
+ }
206
+
207
+ /**
208
+ * Subtle colored shadow for cards and elevated surfaces.
209
+ * Uses Material 3 elevation with optional color tinting.
210
+ */
211
+ fun Modifier.cardShadow(
212
+ color: Color = Color.Black,
213
+ elevation: Float = 4f
214
+ ): Modifier = composed {
215
+ this.shadow(
216
+ elevation = elevation.dp,
217
+ ambientColor = color.copy(alpha = 0.08f),
218
+ spotColor = color.copy(alpha = 0.12f),
219
+ shape = androidx.compose.foundation.shape.RoundedCornerShape(12.dp)
220
+ )
221
+ }
222
+
223
+ /**
224
+ * Deeper shadow for floating elements (FABs, modals).
225
+ */
226
+ fun Modifier.elevatedShadow(
227
+ color: Color = Color.Black
228
+ ): Modifier = composed {
229
+ this.shadow(
230
+ elevation = 8.dp,
231
+ ambientColor = color.copy(alpha = 0.12f),
232
+ spotColor = color.copy(alpha = 0.16f),
233
+ shape = androidx.compose.foundation.shape.RoundedCornerShape(16.dp)
234
+ )
235
+ }
236
+
237
+ /**
238
+ * Shimmer loading overlay for skeleton placeholder views.
239
+ * Sweeps a translucent gradient across the content repeatedly.
240
+ */
241
+ fun Modifier.shimmer(
242
+ durationMs: Int = 1500
243
+ ): Modifier = composed {
244
+ val transition = rememberInfiniteTransition(label = "shimmer")
245
+ val translateAnim by transition.animateFloat(
246
+ initialValue = -1f,
247
+ targetValue = 2f,
248
+ animationSpec = infiniteRepeatable(
249
+ animation = tween(durationMillis = durationMs, easing = LinearEasing),
250
+ repeatMode = RepeatMode.Restart
251
+ ),
252
+ label = "shimmerTranslate"
253
+ )
254
+
255
+ this.alpha(0.3f + 0.7f * ((translateAnim + 1f) / 3f).coerceIn(0f, 1f))
256
+ }
257
+
258
+ /**
259
+ * Repeating scale pulse animation for live indicators and notifications.
260
+ */
261
+ fun Modifier.pulse(
262
+ intensity: Float = 0.05f,
263
+ durationMs: Int = 1000
264
+ ): Modifier = composed {
265
+ val transition = rememberInfiniteTransition(label = "pulse")
266
+ val scale by transition.animateFloat(
267
+ initialValue = 1f,
268
+ targetValue = 1f + intensity,
269
+ animationSpec = infiniteRepeatable(
270
+ animation = tween(durationMillis = durationMs, easing = FastOutSlowInEasing),
271
+ repeatMode = RepeatMode.Reverse
272
+ ),
273
+ label = "pulseScale"
274
+ )
275
+
276
+ this.scale(scale)
277
+ }
278
+
279
+ /**
280
+ * Heart/like bounce effect when toggled active.
281
+ * Scales up to 1.3x then springs back. Perfect for favorite buttons.
282
+ */
283
+ fun Modifier.heartBounce(
284
+ isActive: Boolean
285
+ ): Modifier = composed {
286
+ var previousActive by remember { mutableStateOf(isActive) }
287
+ var animatedScale by remember { mutableFloatStateOf(1f) }
288
+
289
+ val bounceAnim by animateFloatAsState(
290
+ targetValue = animatedScale,
291
+ animationSpec = spring(
292
+ dampingRatio = Spring.DampingRatioMediumBouncy,
293
+ stiffness = Spring.StiffnessMedium
294
+ ),
295
+ label = "heartBounce"
296
+ )
297
+
298
+ LaunchedEffect(isActive) {
299
+ if (isActive && !previousActive) {
300
+ animatedScale = 1.3f
301
+ kotlinx.coroutines.delay(200)
302
+ animatedScale = 1f
303
+ }
304
+ previousActive = isActive
305
+ }
306
+
307
+ this.scale(bounceAnim)
308
+ }