stitch-kit 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/AGENTS.md +139 -0
  2. package/CHANGELOG.md +86 -0
  3. package/README.md +167 -0
  4. package/agents/stitch-kit.md +93 -0
  5. package/bin/stitch-kit.mjs +430 -0
  6. package/docs/architecture.md +118 -0
  7. package/docs/color-prompt-guide.md +119 -0
  8. package/docs/mcp-naming-convention.md +64 -0
  9. package/docs/mcp-schemas/README.md +130 -0
  10. package/docs/mcp-schemas/apply_design_system.json +36 -0
  11. package/docs/mcp-schemas/create_design_system.json +78 -0
  12. package/docs/mcp-schemas/create_project.json +290 -0
  13. package/docs/mcp-schemas/delete_project.json +20 -0
  14. package/docs/mcp-schemas/edit_screens.json +46 -0
  15. package/docs/mcp-schemas/generate_screen_from_text.json +242 -0
  16. package/docs/mcp-schemas/generate_variants.json +77 -0
  17. package/docs/mcp-schemas/get_project.json +137 -0
  18. package/docs/mcp-schemas/get_screen.json +92 -0
  19. package/docs/mcp-schemas/list_design_systems.json +32 -0
  20. package/docs/mcp-schemas/list_projects.json +136 -0
  21. package/docs/mcp-schemas/list_screens.json +56 -0
  22. package/docs/mcp-schemas/update_design_system.json +32 -0
  23. package/docs/mcp-schemas/upload_screens_from_images.json +52 -0
  24. package/docs/prd-to-stitch-workflow.md +137 -0
  25. package/docs/skills-index.md +108 -0
  26. package/docs/tailwind-reference.md +207 -0
  27. package/package.json +41 -0
  28. package/skills/stitch-a11y/SKILL.md +428 -0
  29. package/skills/stitch-a11y/resources/audit-checklist.md +102 -0
  30. package/skills/stitch-animate/SKILL.md +371 -0
  31. package/skills/stitch-animate/resources/animation-patterns.md +248 -0
  32. package/skills/stitch-design-md/SKILL.md +215 -0
  33. package/skills/stitch-design-md/examples/DESIGN.md +54 -0
  34. package/skills/stitch-design-md/examples/usage.md +67 -0
  35. package/skills/stitch-design-md/scripts/fetch-stitch.sh +35 -0
  36. package/skills/stitch-design-system/SKILL.md +314 -0
  37. package/skills/stitch-design-system/resources/tokens-template.css +237 -0
  38. package/skills/stitch-html-components/SKILL.md +344 -0
  39. package/skills/stitch-html-components/resources/architecture-checklist.md +74 -0
  40. package/skills/stitch-html-components/scripts/fetch-stitch.sh +45 -0
  41. package/skills/stitch-loop/SKILL.md +183 -0
  42. package/skills/stitch-loop/examples/SITE.md +39 -0
  43. package/skills/stitch-loop/examples/next-prompt.md +24 -0
  44. package/skills/stitch-loop/examples/usage.md +77 -0
  45. package/skills/stitch-mcp-apply-design-system/SKILL.md +82 -0
  46. package/skills/stitch-mcp-create-design-system/SKILL.md +117 -0
  47. package/skills/stitch-mcp-create-project/SKILL.md +77 -0
  48. package/skills/stitch-mcp-delete-project/SKILL.md +62 -0
  49. package/skills/stitch-mcp-edit-screens/SKILL.md +121 -0
  50. package/skills/stitch-mcp-generate-screen-from-text/SKILL.md +102 -0
  51. package/skills/stitch-mcp-generate-screen-from-text/examples/desktop.md +53 -0
  52. package/skills/stitch-mcp-generate-screen-from-text/examples/mobile.md +71 -0
  53. package/skills/stitch-mcp-generate-variants/SKILL.md +124 -0
  54. package/skills/stitch-mcp-get-project/SKILL.md +67 -0
  55. package/skills/stitch-mcp-get-screen/SKILL.md +117 -0
  56. package/skills/stitch-mcp-get-screen/scripts/fetch-stitch.sh +35 -0
  57. package/skills/stitch-mcp-list-design-systems/SKILL.md +84 -0
  58. package/skills/stitch-mcp-list-projects/SKILL.md +77 -0
  59. package/skills/stitch-mcp-list-screens/SKILL.md +69 -0
  60. package/skills/stitch-mcp-update-design-system/SKILL.md +82 -0
  61. package/skills/stitch-mcp-upload-screens-from-images/SKILL.md +95 -0
  62. package/skills/stitch-mcp-upload-screens-from-images/scripts/encode-image.sh +43 -0
  63. package/skills/stitch-nextjs-components/SKILL.md +181 -0
  64. package/skills/stitch-nextjs-components/resources/architecture-checklist.md +65 -0
  65. package/skills/stitch-nextjs-components/resources/component-template.tsx +101 -0
  66. package/skills/stitch-nextjs-components/scripts/fetch-stitch.sh +45 -0
  67. package/skills/stitch-orchestrator/SKILL.md +337 -0
  68. package/skills/stitch-orchestrator/examples/workflow.md +173 -0
  69. package/skills/stitch-react-components/SKILL.md +236 -0
  70. package/skills/stitch-react-components/references/tailwind-to-react.md +117 -0
  71. package/skills/stitch-react-components/resources/architecture-checklist.md +34 -0
  72. package/skills/stitch-react-components/resources/component-template.tsx +35 -0
  73. package/skills/stitch-react-components/scripts/fetch-stitch.sh +35 -0
  74. package/skills/stitch-react-native-components/SKILL.md +333 -0
  75. package/skills/stitch-react-native-components/resources/architecture-checklist.md +74 -0
  76. package/skills/stitch-react-native-components/resources/component-template.tsx +104 -0
  77. package/skills/stitch-react-native-components/scripts/fetch-stitch.sh +45 -0
  78. package/skills/stitch-remotion/SKILL.md +280 -0
  79. package/skills/stitch-setup/SKILL.md +183 -0
  80. package/skills/stitch-shadcn-ui/SKILL.md +255 -0
  81. package/skills/stitch-skill-creator/SKILL.md +257 -0
  82. package/skills/stitch-skill-creator/references/output-patterns.md +71 -0
  83. package/skills/stitch-skill-creator/scripts/init_stitch_skill.py +229 -0
  84. package/skills/stitch-svelte-components/SKILL.md +282 -0
  85. package/skills/stitch-svelte-components/resources/architecture-checklist.md +62 -0
  86. package/skills/stitch-svelte-components/resources/component-template.svelte +193 -0
  87. package/skills/stitch-svelte-components/scripts/fetch-stitch.sh +36 -0
  88. package/skills/stitch-swiftui-components/SKILL.md +424 -0
  89. package/skills/stitch-swiftui-components/resources/architecture-checklist.md +83 -0
  90. package/skills/stitch-swiftui-components/resources/component-template.swift +131 -0
  91. package/skills/stitch-swiftui-components/resources/layout-mapping.md +155 -0
  92. package/skills/stitch-swiftui-components/scripts/fetch-stitch.sh +45 -0
  93. package/skills/stitch-ued-guide/SKILL.md +124 -0
  94. package/skills/stitch-ui-design-spec-generator/SKILL.md +115 -0
  95. package/skills/stitch-ui-design-spec-generator/examples/usage.md +79 -0
  96. package/skills/stitch-ui-design-variants/SKILL.md +127 -0
  97. package/skills/stitch-ui-prompt-architect/SKILL.md +196 -0
  98. package/skills/stitch-ui-prompt-architect/references/KEYWORDS.md +170 -0
@@ -0,0 +1,102 @@
1
+ # Accessibility Pre-Ship Checklist
2
+
3
+ Quick reference before every production deployment.
4
+ Target: **WCAG 2.1 AA**.
5
+
6
+ ---
7
+
8
+ ## 🏗 Semantic HTML
9
+
10
+ - [ ] Page has exactly one `<main>` landmark
11
+ - [ ] Navigation uses `<nav aria-label="...">` (label required when multiple navs exist)
12
+ - [ ] `<header>`, `<footer>`, `<aside>` used for landmark regions
13
+ - [ ] Heading hierarchy is sequential — no skipped levels (e.g., h1 → h3 without h2)
14
+ - [ ] Lists use `<ul>` / `<ol>` + `<li>`, not `<div>` + `<div>`
15
+ - [ ] Tables have `<caption>` and `<th scope="col/row">` headers
16
+ - [ ] Forms use `<label for="id">` or `aria-label` on every input
17
+
18
+ ---
19
+
20
+ ## 🏷 ARIA
21
+
22
+ - [ ] No `role="button"` on a real `<button>` (redundant)
23
+ - [ ] No ARIA used where semantic HTML already conveys the meaning
24
+ - [ ] Every `aria-labelledby` and `aria-describedby` references a real ID that exists
25
+ - [ ] Disclosure widgets (accordion, dropdown) have `aria-expanded` on the trigger
26
+ - [ ] Modal dialogs have `role="dialog"`, `aria-modal="true"`, `aria-labelledby`
27
+ - [ ] Loading/status updates use `aria-live="polite"` or `aria-live="assertive"`
28
+ - [ ] Icon-only interactive elements have `aria-label`
29
+ - [ ] Decorative images have `alt=""` and `aria-hidden="true"`
30
+
31
+ ---
32
+
33
+ ## ⌨️ Keyboard navigation
34
+
35
+ - [ ] Tab order follows visual reading order (no `tabIndex={1}` or higher)
36
+ - [ ] All interactive elements are reachable by Tab
37
+ - [ ] Modals: focus moves into modal on open, returns to trigger on close
38
+ - [ ] Dropdowns: Escape closes and returns focus to trigger
39
+ - [ ] Custom interactive elements: Enter / Space activates them
40
+ - [ ] No keyboard traps (except intentional modal focus traps)
41
+ - [ ] Skip link is present and works (first focusable element on page)
42
+
43
+ ---
44
+
45
+ ## 👁 Focus visibility
46
+
47
+ - [ ] No `outline: none` or `outline: 0` without a visible custom focus indicator
48
+ - [ ] Focus ring is visible in both light and dark mode
49
+ - [ ] Focus ring has sufficient contrast against all backgrounds it appears on
50
+ - [ ] `:focus-visible` used (not `:focus`) to avoid showing ring on mouse click
51
+
52
+ ---
53
+
54
+ ## 🖼 Images & media
55
+
56
+ - [ ] All `<img>` / `<Image>` have `alt` attribute
57
+ - [ ] Meaningful images have descriptive alt text
58
+ - [ ] Decorative images have `alt=""`
59
+ - [ ] Videos have captions or transcripts
60
+ - [ ] Audio has transcripts
61
+
62
+ ---
63
+
64
+ ## 🎨 Color & contrast
65
+
66
+ - [ ] Body text on background ≥ 4.5:1 contrast ratio
67
+ - [ ] Large text (18px+ regular or 14px+ bold) on background ≥ 3:1
68
+ - [ ] Interactive element boundaries visible against adjacent colors (≥ 3:1)
69
+ - [ ] Errors not indicated by color alone — also include icon or text
70
+ - [ ] Required fields not indicated by color alone — include `(required)` text or aria
71
+
72
+ ---
73
+
74
+ ## 🎬 Motion
75
+
76
+ - [ ] `@media (prefers-reduced-motion: reduce)` override in global CSS
77
+ - [ ] No autoplay video longer than 5 seconds (or provide pause control)
78
+ - [ ] No content that flashes more than 3 times per second
79
+
80
+ ---
81
+
82
+ ## 🧪 How to test
83
+
84
+ **Keyboard only:**
85
+ 1. Unplug/disable mouse
86
+ 2. Tab through the entire page
87
+ 3. Verify every action is reachable and operable
88
+
89
+ **Screen reader:**
90
+ - macOS: VoiceOver (Cmd+F5) + Safari
91
+ - Windows: NVDA (free) + Chrome
92
+ - iOS: VoiceOver + Safari
93
+ - Android: TalkBack + Chrome
94
+
95
+ **Automated:**
96
+ - axe DevTools browser extension (free tier covers ~30% of WCAG issues)
97
+ - Lighthouse → Accessibility panel
98
+ - `npx axe-cli http://localhost:3000` for CI
99
+
100
+ **Contrast:**
101
+ - browser-native: Chrome DevTools → Elements → Accessibility tab → contrast ratio
102
+ - WebAIM Contrast Checker: https://webaim.org/resources/contrastchecker/
@@ -0,0 +1,371 @@
1
+ ---
2
+ name: stitch-animate
3
+ description: Adds a purposeful animation layer to Stitch-generated components — CSS transitions, Framer Motion (React/Next.js), or Svelte transitions. Always respects prefers-reduced-motion.
4
+ allowed-tools:
5
+ - "Read"
6
+ - "Write"
7
+ - "Bash"
8
+ ---
9
+
10
+ # Stitch Animation Layer
11
+
12
+ You are a motion design engineer. You add purposeful animation to existing Stitch-generated components — you don't rebuild them. Your output enhances components with the right motion for the right moment, and is always `prefers-reduced-motion` safe.
13
+
14
+ **Run this skill AFTER** component generation (`stitch-nextjs-components` or `stitch-svelte-components`), not before.
15
+
16
+ ## When to use this skill
17
+
18
+ Use this skill when:
19
+ - Components are generated and working, but feel static
20
+ - User mentions "animations", "transitions", "motion", "hover effects", "scroll reveal"
21
+ - The Stitch design screenshot clearly shows motion intent (overlapping elements, hero sections, dashboards)
22
+ - Adding polish to a completed component set
23
+
24
+ ## The three motion tiers
25
+
26
+ Analyze the design first. Assign animations by tier — don't animate everything:
27
+
28
+ | Tier | What | Duration | Easing | Examples |
29
+ |------|------|----------|--------|---------|
30
+ | **Micro** | Hover, focus, active states on interactive elements | 100–200ms | ease-out | Button hover, link color, icon scale |
31
+ | **Meso** | UI elements entering or leaving the viewport | 250–400ms | cubic-bezier(0,0,0.2,1) | Card reveals, sidebar slide, modal open |
32
+ | **Macro** | Full page or section transitions | 400–600ms | ease-in-out | Route transitions, hero section, onboarding |
33
+
34
+ **Rule of thumb:** If in doubt, use Micro. Over-animation is worse than no animation.
35
+
36
+ ## Step 1: Audit the components
37
+
38
+ Read the generated component files. For each one, identify:
39
+
40
+ 1. **Interactive elements** that need Micro tier (buttons, links, inputs, toggles, cards with `onClick`)
41
+ 2. **Revealed elements** that benefit from Meso tier (page sections, cards grids, sidebars, modals, drawers, toasts)
42
+ 3. **Hero or landmark elements** that warrant Macro tier (the primary headline, featured images, page-level transitions)
43
+
44
+ Only animate elements that have clear purpose. If you can't explain in one sentence *why* an element animates, don't animate it.
45
+
46
+ ## Step 2: Detect the framework and choose the animation approach
47
+
48
+ Read `package.json` to determine the framework, then use the matching approach:
49
+
50
+ | Framework | Approach |
51
+ |-----------|---------|
52
+ | Next.js / React | CSS + optionally Framer Motion |
53
+ | SvelteKit / Svelte | Built-in Svelte transitions + CSS |
54
+ | Vanilla HTML | CSS only |
55
+
56
+ ---
57
+
58
+ ## Approach A: CSS transitions and animations (universal)
59
+
60
+ Use CSS for Micro tier and simple Meso. Zero dependencies.
61
+
62
+ ### Micro tier — interactive states
63
+
64
+ Add these to `design-tokens.css` or the component's CSS:
65
+ ```css
66
+ /* Base transition shorthand — use on all interactive elements */
67
+ .transition-base {
68
+ transition:
69
+ background-color var(--motion-duration-fast) var(--motion-ease-default),
70
+ color var(--motion-duration-fast) var(--motion-ease-default),
71
+ border-color var(--motion-duration-fast) var(--motion-ease-default),
72
+ box-shadow var(--motion-duration-fast) var(--motion-ease-default),
73
+ transform var(--motion-duration-fast) var(--motion-ease-default),
74
+ opacity var(--motion-duration-fast) var(--motion-ease-default);
75
+ }
76
+
77
+ /* Button micro-interaction */
78
+ .btn {
79
+ transition: transform 150ms ease-out, box-shadow 150ms ease-out, background-color 150ms ease-out;
80
+ }
81
+ .btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
82
+ .btn:active { transform: translateY(0); box-shadow: var(--shadow-sm); }
83
+
84
+ /* Card lift */
85
+ .card {
86
+ transition: transform 200ms ease-out, box-shadow 200ms ease-out;
87
+ }
88
+ .card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
89
+ ```
90
+
91
+ ### Meso tier — element reveal
92
+
93
+ Use keyframe animations with `animation-fill-mode: both`:
94
+ ```css
95
+ @keyframes fade-up {
96
+ from { opacity: 0; transform: translateY(16px); }
97
+ to { opacity: 1; transform: translateY(0); }
98
+ }
99
+
100
+ @keyframes fade-in {
101
+ from { opacity: 0; }
102
+ to { opacity: 1; }
103
+ }
104
+
105
+ @keyframes slide-in-right {
106
+ from { opacity: 0; transform: translateX(24px); }
107
+ to { opacity: 1; transform: translateX(0); }
108
+ }
109
+
110
+ .animate-fade-up { animation: fade-up var(--motion-duration-base) var(--motion-ease-out) both; }
111
+ .animate-fade-in { animation: fade-in var(--motion-duration-fast) var(--motion-ease-out) both; }
112
+ .animate-slide-in-r { animation: slide-in-right var(--motion-duration-base) var(--motion-ease-out) both; }
113
+
114
+ /* Stagger children with CSS custom property */
115
+ .stagger-children > * {
116
+ animation-delay: calc(var(--stagger-index, 0) * 60ms);
117
+ }
118
+ ```
119
+
120
+ ### prefers-reduced-motion (REQUIRED)
121
+
122
+ Always add this override at the end of every animation CSS block:
123
+ ```css
124
+ @media (prefers-reduced-motion: reduce) {
125
+ *,
126
+ *::before,
127
+ *::after {
128
+ animation-duration: 0.01ms !important;
129
+ animation-iteration-count: 1 !important;
130
+ transition-duration: 0.01ms !important;
131
+ scroll-behavior: auto !important;
132
+ }
133
+ }
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Approach B: Framer Motion (React / Next.js)
139
+
140
+ Use Framer Motion for Meso and Macro tier in React projects. It handles `prefers-reduced-motion` natively via `useReducedMotion`.
141
+
142
+ ### Installation
143
+ ```bash
144
+ npm install framer-motion
145
+ ```
146
+
147
+ ### Scroll-triggered reveals (most common use case)
148
+
149
+ ```tsx
150
+ 'use client'
151
+
152
+ import { motion, useReducedMotion } from 'framer-motion'
153
+
154
+ /**
155
+ * Wraps children in a scroll-triggered fade+rise animation.
156
+ * Automatically disables animation when prefers-reduced-motion is active.
157
+ */
158
+ export function RevealOnScroll({ children, delay = 0 }: {
159
+ children: React.ReactNode
160
+ delay?: number
161
+ }) {
162
+ const shouldReduce = useReducedMotion()
163
+
164
+ return (
165
+ <motion.div
166
+ initial={shouldReduce ? false : { opacity: 0, y: 20 }}
167
+ whileInView={{ opacity: 1, y: 0 }}
168
+ viewport={{ once: true, margin: '-50px' }}
169
+ transition={{
170
+ duration: 0.4,
171
+ ease: [0, 0, 0.2, 1],
172
+ delay,
173
+ }}
174
+ >
175
+ {children}
176
+ </motion.div>
177
+ )
178
+ }
179
+ ```
180
+
181
+ ### Staggered card grid
182
+
183
+ ```tsx
184
+ 'use client'
185
+
186
+ import { motion, useReducedMotion } from 'framer-motion'
187
+
188
+ const container = {
189
+ hidden: { opacity: 0 },
190
+ show: {
191
+ opacity: 1,
192
+ transition: { staggerChildren: 0.08 }
193
+ }
194
+ }
195
+
196
+ const item = {
197
+ hidden: { opacity: 0, y: 16 },
198
+ show: { opacity: 1, y: 0, transition: { ease: [0, 0, 0.2, 1], duration: 0.35 } }
199
+ }
200
+
201
+ export function AnimatedGrid({ cards }: { cards: CardProps[] }) {
202
+ const shouldReduce = useReducedMotion()
203
+
204
+ if (shouldReduce) {
205
+ return <div className="grid">{cards.map(c => <Card key={c.id} {...c} />)}</div>
206
+ }
207
+
208
+ return (
209
+ <motion.div className="grid" variants={container} initial="hidden" whileInView="show" viewport={{ once: true }}>
210
+ {cards.map(c => (
211
+ <motion.div key={c.id} variants={item}>
212
+ <Card {...c} />
213
+ </motion.div>
214
+ ))}
215
+ </motion.div>
216
+ )
217
+ }
218
+ ```
219
+
220
+ ### Page transition wrapper (App Router)
221
+
222
+ ```tsx
223
+ // app/template.tsx — wraps every page with a transition
224
+ 'use client'
225
+
226
+ import { motion } from 'framer-motion'
227
+
228
+ export default function Template({ children }: { children: React.ReactNode }) {
229
+ return (
230
+ <motion.div
231
+ initial={{ opacity: 0 }}
232
+ animate={{ opacity: 1 }}
233
+ exit={{ opacity: 0 }}
234
+ transition={{ duration: 0.2 }}
235
+ >
236
+ {children}
237
+ </motion.div>
238
+ )
239
+ }
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Approach C: Svelte transitions (Svelte / SvelteKit)
245
+
246
+ Svelte's built-in transitions are the cleanest option for Svelte projects — zero dependencies.
247
+
248
+ ### Intersection Observer for scroll reveals
249
+
250
+ Svelte doesn't have a built-in scroll reveal, but the `use:` directive makes this clean:
251
+
252
+ ```svelte
253
+ <script lang="ts">
254
+ import { fade, fly } from 'svelte/transition'
255
+ import { cubicOut } from 'svelte/easing'
256
+
257
+ /**
258
+ * Svelte action that triggers a fade-up animation when the element
259
+ * enters the viewport. Respects prefers-reduced-motion.
260
+ */
261
+ function revealOnScroll(node: HTMLElement) {
262
+ const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
263
+
264
+ if (prefersReduced) return {}
265
+
266
+ node.style.opacity = '0'
267
+ node.style.transform = 'translateY(16px)'
268
+
269
+ const observer = new IntersectionObserver(
270
+ (entries) => {
271
+ if (entries[0].isIntersecting) {
272
+ node.style.transition = `opacity 400ms cubic-bezier(0,0,0.2,1), transform 400ms cubic-bezier(0,0,0.2,1)`
273
+ node.style.opacity = '1'
274
+ node.style.transform = 'translateY(0)'
275
+ observer.unobserve(node)
276
+ }
277
+ },
278
+ { threshold: 0.1, rootMargin: '-50px' }
279
+ )
280
+ observer.observe(node)
281
+
282
+ return {
283
+ destroy() { observer.disconnect() }
284
+ }
285
+ }
286
+ </script>
287
+
288
+ <!-- Use on any element -->
289
+ <section use:revealOnScroll>
290
+ <h2>This section fades in on scroll</h2>
291
+ </section>
292
+ ```
293
+
294
+ ### Animated list entries
295
+
296
+ ```svelte
297
+ <script lang="ts">
298
+ import { fly } from 'svelte/transition'
299
+ import { quintOut } from 'svelte/easing'
300
+
301
+ let items = $state<Item[]>([...])
302
+ </script>
303
+
304
+ {#each items as item, i (item.id)}
305
+ <div
306
+ in:fly={{ y: 16, duration: 300, delay: i * 60, easing: quintOut }}
307
+ out:fade={{ duration: 150 }}
308
+ >
309
+ <ItemCard {...item} />
310
+ </div>
311
+ {/each}
312
+ ```
313
+
314
+ ### Modal/drawer with enter/exit
315
+
316
+ ```svelte
317
+ <script lang="ts">
318
+ import { fade, fly } from 'svelte/transition'
319
+ let { isOpen = false } = $props()
320
+ </script>
321
+
322
+ {#if isOpen}
323
+ <!-- Backdrop -->
324
+ <div
325
+ class="backdrop"
326
+ transition:fade={{ duration: 200 }}
327
+ role="presentation"
328
+ />
329
+
330
+ <!-- Drawer -->
331
+ <aside
332
+ class="drawer"
333
+ transition:fly={{ x: 320, duration: 300, easing: cubicOut }}
334
+ role="dialog"
335
+ aria-modal="true"
336
+ >
337
+ {@render children()}
338
+ </aside>
339
+ {/if}
340
+ ```
341
+
342
+ ## Step 3: Apply animations to existing components
343
+
344
+ When modifying existing files:
345
+
346
+ 1. **Read each component file** first — understand the current structure
347
+ 2. **Add CSS classes** for Micro tier only (never change the component's logic for Micro)
348
+ 3. **Wrap with motion components** for Meso/Macro (React) or **add transition directives** (Svelte)
349
+ 4. **Add the reduced-motion override** to the main CSS file if not already present
350
+ 5. **Test both states** — with and without animation (use browser DevTools to simulate reduced motion)
351
+
352
+ ## What NOT to animate
353
+
354
+ - Navigation links — stick to color/underline transitions only
355
+ - Scrolling behavior — only `scroll-behavior: smooth` where appropriate, and even that needs the reduced-motion override
356
+ - Data tables — distract from reading; use subtle row hover only
357
+ - Every element on a page — choose 2-3 anchor animations per screen
358
+
359
+ ## Troubleshooting
360
+
361
+ | Issue | Fix |
362
+ |-------|-----|
363
+ | Animation not playing | Check the element is in the DOM before the animation fires |
364
+ | Framer Motion hydration error | Ensure component has `'use client'` directive |
365
+ | Svelte transition plays twice | Check for double-render in dev mode (StrictMode equivalent) |
366
+ | Animation jank/lag | Add `will-change: transform, opacity` sparingly to animated elements |
367
+ | Reduced motion not stopping animation | Ensure `@media (prefers-reduced-motion)` is loaded AFTER animation CSS |
368
+
369
+ ## References
370
+
371
+ - `resources/animation-patterns.md` — Catalog of copy-paste ready patterns for common UI components