arkaos 5.4.0 → 5.6.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 (55) hide show
  1. package/README.md +2 -2
  2. package/THE-ARKAOS-GUIDE.md +1 -1
  3. package/VERSION +1 -1
  4. package/arka/SKILL.md +1 -1
  5. package/config/skills-provenance.yaml +27 -0
  6. package/departments/dev/skills/canvas-generative/SKILL.md +362 -0
  7. package/departments/dev/skills/canvas-generative/references/algorithms.md +934 -0
  8. package/departments/dev/skills/canvas-generative/references/genjutsu.LICENSE +21 -0
  9. package/departments/dev/skills/css-native/SKILL.md +353 -0
  10. package/departments/dev/skills/css-native/references/genjutsu.LICENSE +21 -0
  11. package/departments/dev/skills/css-native/references/modern-css.md +465 -0
  12. package/departments/dev/skills/framer-motion/SKILL.md +223 -0
  13. package/departments/dev/skills/framer-motion/references/api.md +312 -0
  14. package/departments/dev/skills/framer-motion/references/genjutsu.LICENSE +21 -0
  15. package/departments/dev/skills/threejs/SKILL.md +173 -0
  16. package/departments/dev/skills/threejs/references/genjutsu.LICENSE +21 -0
  17. package/departments/dev/skills/threejs/references/r3f.md +249 -0
  18. package/departments/dev/skills/threejs/references/scene-setup.md +404 -0
  19. package/departments/dev/skills/threejs/references/shaders.md +452 -0
  20. package/harness/codex/AGENTS.md +1 -1
  21. package/harness/copilot/copilot-instructions.md +1 -1
  22. package/harness/cursor/rules/arkaos.mdc +2 -2
  23. package/harness/gemini/GEMINI.md +1 -1
  24. package/harness/opencode/AGENTS.md +1 -1
  25. package/harness/opencode/agents/arka-architect-gabriel.md +1 -1
  26. package/harness/opencode/agents/arka-brand-director-valentina.md +1 -1
  27. package/harness/opencode/agents/arka-cfo-helena.md +1 -1
  28. package/harness/opencode/agents/arka-chief-of-staff-afonso.md +1 -1
  29. package/harness/opencode/agents/arka-community-strategist-beatriz.md +1 -1
  30. package/harness/opencode/agents/arka-content-strategist-rafael.md +1 -1
  31. package/harness/opencode/agents/arka-conversion-strategist-ines.md +1 -1
  32. package/harness/opencode/agents/arka-coo-sofia.md +1 -1
  33. package/harness/opencode/agents/arka-copy-director-eduardo.md +1 -1
  34. package/harness/opencode/agents/arka-cqo-marta.md +1 -1
  35. package/harness/opencode/agents/arka-cto-marco.md +1 -1
  36. package/harness/opencode/agents/arka-design-ops-lead-iris.md +1 -1
  37. package/harness/opencode/agents/arka-ecom-director-ricardo.md +1 -1
  38. package/harness/opencode/agents/arka-knowledge-director-clara.md +1 -1
  39. package/harness/opencode/agents/arka-leadership-director-rodrigo.md +1 -1
  40. package/harness/opencode/agents/arka-marketing-director-luna.md +1 -1
  41. package/harness/opencode/agents/arka-ops-lead-daniel.md +1 -1
  42. package/harness/opencode/agents/arka-pm-director-carolina.md +1 -1
  43. package/harness/opencode/agents/arka-revops-lead-vicente.md +1 -1
  44. package/harness/opencode/agents/arka-saas-strategist-tiago.md +1 -1
  45. package/harness/opencode/agents/arka-sales-director-miguel.md +1 -1
  46. package/harness/opencode/agents/arka-strategy-director-tomas.md +1 -1
  47. package/harness/opencode/agents/arka-tech-director-francisca.md +1 -1
  48. package/harness/opencode/agents/arka-tech-lead-paulo.md +1 -1
  49. package/harness/opencode/agents/arka-video-producer-simao.md +1 -1
  50. package/harness/zed/.rules +1 -1
  51. package/knowledge/commands-registry.json +1 -1
  52. package/knowledge/skills-manifest.json +61 -1
  53. package/package.json +1 -1
  54. package/pyproject.toml +1 -1
  55. package/scripts/marketplace_gen.py +1 -1
@@ -0,0 +1,465 @@
1
+ # Modern CSS — Browser Support, Fallbacks & Progressive Enhancement
2
+
3
+ > Last verified: March 2026
4
+
5
+ ---
6
+
7
+ ## Browser Support Tables
8
+
9
+ ### Scroll-Driven Animations (`animation-timeline`)
10
+
11
+ | Browser | Version | Status |
12
+ |---|---|---|
13
+ | Chrome | 115+ | Supported |
14
+ | Edge | 115+ | Supported |
15
+ | Firefox | 128+ | Supported (shipped July 2024) |
16
+ | Safari | 18.4+ | Supported (shipped early 2025) |
17
+
18
+ **Global coverage**: ~90%+ (as of March 2026)
19
+
20
+ ### View Transitions API
21
+
22
+ | Feature | Chrome | Edge | Firefox | Safari |
23
+ |---|---|---|---|---|
24
+ | Same-document (`startViewTransition`) | 111+ | 111+ | 133+ | 18+ |
25
+ | Cross-document (`@view-transition`) | 126+ | 126+ | Not yet | 18.2+ |
26
+ | `view-transition-class` | 125+ | 125+ | Not yet | 18.2+ |
27
+
28
+ **Note**: Cross-document view transitions are an Interop 2026 focus area — Firefox support expected to land in 2026.
29
+
30
+ ### @starting-style
31
+
32
+ | Browser | Version | Status |
33
+ |---|---|---|
34
+ | Chrome | 117+ | Supported |
35
+ | Edge | 117+ | Supported |
36
+ | Firefox | 129+ | Supported |
37
+ | Safari | 17.5+ | Supported |
38
+
39
+ **Global coverage**: ~93%+ — Baseline Newly Available (2024)
40
+
41
+ ### CSS Anchor Positioning
42
+
43
+ | Browser | Version | Status |
44
+ |---|---|---|
45
+ | Chrome | 125+ | Supported |
46
+ | Edge | 125+ | Supported |
47
+ | Firefox | Nightly | In development (Interop 2026) |
48
+ | Safari | 26+ | Supported (shipped 2026) |
49
+
50
+ **Note**: Anchor positioning is an Interop 2026 focus area. Firefox expected to ship stable support in 2026.
51
+
52
+ ### Container Queries
53
+
54
+ | Feature | Chrome | Edge | Firefox | Safari |
55
+ |---|---|---|---|---|
56
+ | Size queries (`@container`) | 105+ | 105+ | 110+ | 16+ |
57
+ | Container-relative units (`cqw`, `cqh`) | 105+ | 105+ | 110+ | 16+ |
58
+ | Style queries (`@container style()`) | 111+ | 111+ | Not yet | 18+ |
59
+
60
+ **Global coverage (size queries)**: ~95%+
61
+
62
+ ---
63
+
64
+ ## Fallback Patterns
65
+
66
+ ### Scroll-Driven Animations
67
+
68
+ ```css
69
+ /* Base: no scroll animation, element is always visible */
70
+ .reveal {
71
+ opacity: 1;
72
+ transform: translateY(0);
73
+ }
74
+
75
+ /* Progressive enhancement for supporting browsers */
76
+ @supports (animation-timeline: scroll()) {
77
+ .reveal {
78
+ animation: reveal-up linear both;
79
+ animation-timeline: view();
80
+ animation-range: entry 10% entry 90%;
81
+ }
82
+
83
+ @keyframes reveal-up {
84
+ from {
85
+ opacity: 0;
86
+ transform: translateY(2rem);
87
+ }
88
+ to {
89
+ opacity: 1;
90
+ transform: translateY(0);
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ **Strategy**: Content is always visible by default. Scroll animation is purely decorative enhancement. Never hide content behind a scroll-driven animation without fallback.
97
+
98
+ ### View Transitions (Same-Document)
99
+
100
+ ```js
101
+ function navigate(updateFn) {
102
+ // Fallback: just update the DOM instantly
103
+ if (!document.startViewTransition) {
104
+ updateFn();
105
+ return;
106
+ }
107
+
108
+ document.startViewTransition(() => updateFn());
109
+ }
110
+ ```
111
+
112
+ ```css
113
+ /* Only apply transition styles if supported */
114
+ @supports (view-transition-name: none) {
115
+ .hero { view-transition-name: hero; }
116
+
117
+ ::view-transition-old(hero) {
118
+ animation: fade-scale-out 250ms ease-out both;
119
+ }
120
+ ::view-transition-new(hero) {
121
+ animation: fade-scale-in 300ms ease-in both;
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### View Transitions (Cross-Document)
127
+
128
+ ```css
129
+ /* This rule is safely ignored by browsers that don't support it */
130
+ @view-transition {
131
+ navigation: auto;
132
+ }
133
+
134
+ /* Guard transition-specific styles */
135
+ @supports (view-transition-name: none) {
136
+ .page-header { view-transition-name: header; }
137
+ .main-content { view-transition-name: content; }
138
+
139
+ ::view-transition-group(header) {
140
+ animation-duration: 300ms;
141
+ }
142
+ ::view-transition-group(content) {
143
+ animation-duration: 250ms;
144
+ }
145
+ }
146
+ ```
147
+
148
+ **Strategy**: Pages load normally in unsupported browsers. The `@view-transition` rule is unknown and ignored — no breakage.
149
+
150
+ ### @starting-style
151
+
152
+ ```css
153
+ /* Broad support — but guard with @supports for very old browsers */
154
+ .popover {
155
+ opacity: 1;
156
+ transform: scale(1);
157
+ transition: opacity 200ms ease, transform 200ms ease;
158
+ }
159
+
160
+ /* @starting-style is baseline — this works in all modern browsers */
161
+ .popover {
162
+ @starting-style {
163
+ opacity: 0;
164
+ transform: scale(0.95);
165
+ }
166
+ }
167
+
168
+ /* For the display transition, check discrete support */
169
+ @supports (transition-behavior: allow-discrete) {
170
+ .popover {
171
+ transition: opacity 200ms ease, transform 200ms ease,
172
+ display 200ms allow-discrete, overlay 200ms allow-discrete;
173
+ }
174
+
175
+ .popover:not(:popover-open) {
176
+ opacity: 0;
177
+ transform: scale(0.95);
178
+ display: none;
179
+ }
180
+ }
181
+ ```
182
+
183
+ **Strategy**: `@starting-style` itself is well-supported. The main concern is `transition-behavior: allow-discrete` for `display`/`overlay` transitions. Guard that part specifically.
184
+
185
+ ### Anchor Positioning
186
+
187
+ ```css
188
+ /* Feature detection for anchor positioning */
189
+ @supports (anchor-name: --a) {
190
+ .trigger { anchor-name: --trigger; }
191
+
192
+ .tooltip {
193
+ position: fixed;
194
+ position-anchor: --trigger;
195
+ position-area: top center;
196
+ margin-bottom: 0.5rem;
197
+
198
+ position-try-fallbacks: --bottom;
199
+ }
200
+
201
+ @position-try --bottom {
202
+ position-area: bottom center;
203
+ margin-top: 0.5rem;
204
+ }
205
+ }
206
+
207
+ /* Fallback for unsupported browsers: manual absolute positioning */
208
+ @supports not (anchor-name: --a) {
209
+ .tooltip-wrapper {
210
+ position: relative;
211
+ }
212
+
213
+ .tooltip {
214
+ position: absolute;
215
+ bottom: 100%;
216
+ left: 50%;
217
+ transform: translateX(-50%);
218
+ margin-bottom: 0.5rem;
219
+ }
220
+ }
221
+ ```
222
+
223
+ **Strategy**: Use `@supports (anchor-name: --a)` to detect. Provide a classic `position: absolute` fallback. For JS-heavy apps, Floating UI remains a solid fallback.
224
+
225
+ ### Container Queries
226
+
227
+ ```css
228
+ /* Container queries are baseline — safe for production */
229
+ .card-wrapper {
230
+ container-type: inline-size;
231
+ container-name: card;
232
+ }
233
+
234
+ /* Size queries: well supported */
235
+ @container card (min-width: 400px) {
236
+ .card { flex-direction: row; }
237
+ }
238
+
239
+ /* Style queries: Chrome/Edge/Safari only — use with care */
240
+ @supports (container-type: inline-size) {
241
+ /* Size queries are safe — 95%+ coverage */
242
+ }
243
+
244
+ /* Style queries: progressive enhancement only */
245
+ @container style(--theme: dark) {
246
+ .card { background: oklch(0.2 0.02 250); }
247
+ }
248
+ /* Fallback: use a class or media query for unsupported browsers */
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Progressive Enhancement Strategies
254
+
255
+ ### Strategy 1: Layered Animation (Recommended)
256
+
257
+ Build in layers — each layer adds richness but nothing breaks without it.
258
+
259
+ ```css
260
+ /* Layer 0: Content is visible, no animation */
261
+ .section-title {
262
+ opacity: 1;
263
+ }
264
+
265
+ /* Layer 1: Simple transition (universally supported) */
266
+ .section-title {
267
+ transition: opacity 400ms ease, transform 400ms ease;
268
+ }
269
+ .section-title.visible {
270
+ opacity: 1;
271
+ transform: translateY(0);
272
+ }
273
+
274
+ /* Layer 2: Scroll-driven (modern browsers only) */
275
+ @supports (animation-timeline: scroll()) {
276
+ .section-title {
277
+ animation: reveal linear both;
278
+ animation-timeline: view();
279
+ animation-range: entry 0% entry 80%;
280
+ /* Remove the JS-toggled class approach */
281
+ transition: none;
282
+ }
283
+
284
+ @keyframes reveal {
285
+ from { opacity: 0; transform: translateY(1.5rem); }
286
+ to { opacity: 1; transform: translateY(0); }
287
+ }
288
+ }
289
+ ```
290
+
291
+ ### Strategy 2: View Transition as Enhancement
292
+
293
+ ```js
294
+ // Router integration example (works with any framework)
295
+ async function navigateTo(url) {
296
+ const response = await fetch(url);
297
+ const html = await response.text();
298
+ const parser = new DOMParser();
299
+ const doc = parser.parseFromString(html, 'text/html');
300
+
301
+ const updateDOM = () => {
302
+ document.title = doc.title;
303
+ document.querySelector('main').replaceWith(
304
+ doc.querySelector('main')
305
+ );
306
+ };
307
+
308
+ if (document.startViewTransition) {
309
+ document.startViewTransition(updateDOM);
310
+ } else {
311
+ updateDOM();
312
+ }
313
+ }
314
+ ```
315
+
316
+ ```css
317
+ /* Cross-document: progressive by nature */
318
+ @view-transition { navigation: auto; }
319
+
320
+ /* Reduce motion: respect user preferences */
321
+ @media (prefers-reduced-motion: reduce) {
322
+ ::view-transition-group(*),
323
+ ::view-transition-old(*),
324
+ ::view-transition-new(*) {
325
+ animation-duration: 0.01ms !important;
326
+ }
327
+ }
328
+ ```
329
+
330
+ ### Strategy 3: @starting-style + Popover API
331
+
332
+ Full native modal with enter/exit animation, zero JavaScript.
333
+
334
+ ```html
335
+ <button popovertarget="menu">Open</button>
336
+
337
+ <div id="menu" popover>
338
+ <p>Menu content</p>
339
+ </div>
340
+ ```
341
+
342
+ ```css
343
+ [popover] {
344
+ /* Open state */
345
+ opacity: 1;
346
+ transform: translateY(0) scale(1);
347
+ transition: opacity 250ms ease, transform 250ms ease,
348
+ display 250ms allow-discrete, overlay 250ms allow-discrete;
349
+
350
+ /* Entry animation */
351
+ @starting-style {
352
+ opacity: 0;
353
+ transform: translateY(-0.5rem) scale(0.97);
354
+ }
355
+ }
356
+
357
+ /* Exit animation */
358
+ [popover]:not(:popover-open) {
359
+ opacity: 0;
360
+ transform: translateY(-0.5rem) scale(0.97);
361
+ }
362
+ ```
363
+
364
+ ### Strategy 4: Anchor + Popover Combo (Animated Tooltip)
365
+
366
+ ```html
367
+ <button anchor="tip" popovertarget="tip">Hover me</button>
368
+
369
+ <div id="tip" popover="hint" anchor="trigger">
370
+ Tooltip content
371
+ </div>
372
+ ```
373
+
374
+ ```css
375
+ [popover="hint"] {
376
+ position: fixed;
377
+ position-anchor: --trigger;
378
+ position-area: top center;
379
+ margin-bottom: 0.5rem;
380
+
381
+ /* Animation */
382
+ opacity: 1;
383
+ transform: translateY(0);
384
+ transition: opacity 150ms ease, transform 150ms ease,
385
+ display 150ms allow-discrete, overlay 150ms allow-discrete;
386
+
387
+ @starting-style {
388
+ opacity: 0;
389
+ transform: translateY(4px);
390
+ }
391
+
392
+ position-try-fallbacks: --bottom, --left, --right;
393
+ }
394
+
395
+ @position-try --bottom {
396
+ position-area: bottom center;
397
+ margin-top: 0.5rem;
398
+ }
399
+ @position-try --left {
400
+ position-area: left center;
401
+ margin-right: 0.5rem;
402
+ }
403
+ @position-try --right {
404
+ position-area: right center;
405
+ margin-left: 0.5rem;
406
+ }
407
+
408
+ /* Respect reduced motion */
409
+ @media (prefers-reduced-motion: reduce) {
410
+ [popover="hint"] {
411
+ transition-duration: 0.01ms;
412
+ }
413
+ }
414
+ ```
415
+
416
+ ---
417
+
418
+ ## Accessibility Checklist
419
+
420
+ ```css
421
+ /* ALWAYS include this in any project with animations */
422
+ @media (prefers-reduced-motion: reduce) {
423
+ *,
424
+ *::before,
425
+ *::after {
426
+ animation-duration: 0.01ms !important;
427
+ animation-iteration-count: 1 !important;
428
+ transition-duration: 0.01ms !important;
429
+ scroll-behavior: auto !important;
430
+ }
431
+ }
432
+ ```
433
+
434
+ For scroll-driven animations specifically:
435
+
436
+ ```css
437
+ @media (prefers-reduced-motion: reduce) {
438
+ .reveal {
439
+ animation: none;
440
+ opacity: 1;
441
+ transform: none;
442
+ }
443
+ }
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Performance Notes
449
+
450
+ | Property | Rendering Cost | GPU Composited |
451
+ |---|---|---|
452
+ | `transform` | Low | Yes |
453
+ | `opacity` | Low | Yes |
454
+ | `filter` / `backdrop-filter` | Medium | Yes |
455
+ | `clip-path` | Medium | Yes (in most browsers) |
456
+ | `background` (gradients) | Medium | No — repaint |
457
+ | `width` / `height` | High | No — reflow + repaint |
458
+ | `top` / `left` / `right` / `bottom` | High | No — reflow + repaint |
459
+ | `box-shadow` | High | No — repaint |
460
+
461
+ Best practices:
462
+ - Use `will-change` sparingly and only on elements about to animate — never `will-change: transform` on 50 elements
463
+ - Prefer `translate`, `scale`, `rotate` individual properties over `transform` shorthand when only one axis changes (allows independent transitions)
464
+ - For scroll-driven animations, the browser automatically optimizes — no `will-change` needed
465
+ - Test with Chrome DevTools > Rendering > "Highlight areas outside the compositing layers" to verify GPU compositing
@@ -0,0 +1,223 @@
1
+ ---
2
+ name: dev/framer-motion
3
+ description: >
4
+ Framer Motion for React: AnimatePresence exit animations, layout
5
+ animations with stable keys, variant propagation and orchestration,
6
+ gestures, and motion values that update without re-render — plus the
7
+ decision rule for when NOT to use it.
8
+ TRIGGER: "framer motion", "motion for React", "AnimatePresence", "layout
9
+ animation", "anima este componente React", "exit animation", "/dev
10
+ framer-motion".
11
+ SKIP: the same effect achievable in pure CSS (scroll-driven, view
12
+ transitions, entry effects) -> dev/css-native (zero dependency beats a
13
+ library); generative canvas work -> dev/canvas-generative.
14
+ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob]
15
+ metadata:
16
+ origin: community
17
+ source: https://github.com/AThevon/genjutsu
18
+ license: MIT
19
+ ---
20
+
21
+ <!-- arka:kb-first-prefix begin -->
22
+ > **KB-first:** query `mcp__obsidian__search_notes` (and
23
+ > `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
24
+ > or graph nodes — or declare the gap — BEFORE any external research.
25
+ > Full doctrine: `arka/SKILL.md` (KB-First Research).
26
+ <!-- arka:kb-first-prefix end -->
27
+
28
+ # Framer Motion — `/dev framer-motion`
29
+
30
+ > **Agent:** Diana (Frontend Dev) | **Framework:** Framer Motion (genjutsu)
31
+
32
+ > Package: `motion` (v11+, formerly `framer-motion`). Import: `import { motion, AnimatePresence } from "motion/react"`
33
+
34
+ ## When to use Framer Motion vs alternatives
35
+
36
+ | Criteria | Framer Motion | GSAP | Native CSS |
37
+ |---------|--------------|------|-----------|
38
+ | Layout animations | Excellent (layoutId) | Manual | Impossible |
39
+ | Exit animations | AnimatePresence | Timeline reverse | Limited (display) |
40
+ | Gestures (drag, hover) | Native, declarative | Draggable plugin | Basic |
41
+ | Scroll-driven | useScroll + useTransform | ScrollTrigger (more powerful) | scroll-timeline |
42
+ | Complex orchestration | Variants + propagation | Timeline (more flexible) | @keyframes |
43
+ | Bundle size | ~50kb tree-shaken | ~30kb core | 0kb |
44
+ | React integration | Native, component-first | Refs + useGSAP | className toggle |
45
+
46
+ **Rule**: Framer Motion for React UI interactions (modals, toasts, reorder, shared layout). GSAP for complex timelines, cinematic scroll-driven, SVG morphing.
47
+
48
+ ## AnimatePresence — Exit animations
49
+
50
+ ```tsx
51
+ <AnimatePresence mode="wait">
52
+ {isVisible && (
53
+ <motion.div
54
+ key="unique-key" // REQUIRED — identifies the component
55
+ initial={{ opacity: 0 }}
56
+ animate={{ opacity: 1 }}
57
+ exit={{ opacity: 0 }}
58
+ />
59
+ )}
60
+ </AnimatePresence>
61
+ ```
62
+
63
+ - `mode="wait"` — waits for exit to finish before enter (page transitions)
64
+ - `mode="sync"` — exit and enter simultaneously
65
+ - `mode="popLayout"` — removes from flow immediately (good for lists)
66
+ - `onExitComplete` — callback when all exit animations are finished
67
+
68
+ ## Layout animations
69
+
70
+ ```tsx
71
+ // Shared layout — the element "slides" between two positions
72
+ <motion.div layoutId="highlight" className={activeTab === id ? "active" : ""} />
73
+
74
+ // Auto layout — animates position/size when layout changes
75
+ <motion.div layout>
76
+ {isExpanded && <motion.p layout>Additional content</motion.p>}
77
+ </motion.div>
78
+
79
+ // layout="position" — animates position only (not size)
80
+ // layout="size" — animates size only
81
+ // layout="preserve-aspect" — preserves the ratio during the transition
82
+ ```
83
+
84
+ ## Variants — Propagation and orchestration
85
+
86
+ ```tsx
87
+ const container = {
88
+ hidden: { opacity: 0 },
89
+ show: {
90
+ opacity: 1,
91
+ transition: {
92
+ staggerChildren: 0.08,
93
+ delayChildren: 0.2,
94
+ staggerDirection: 1, // 1 = normal, -1 = reverse
95
+ },
96
+ },
97
+ };
98
+
99
+ const item = {
100
+ hidden: { opacity: 0, y: 20 },
101
+ show: { opacity: 1, y: 0 },
102
+ };
103
+
104
+ <motion.ul variants={container} initial="hidden" animate="show">
105
+ {items.map((i) => (
106
+ <motion.li key={i.id} variants={item} />
107
+ ))}
108
+ </motion.ul>
109
+ ```
110
+
111
+ Variants **automatically propagate** to motion children — no need for `initial`/`animate` on children.
112
+
113
+ ## Gestures
114
+
115
+ ```tsx
116
+ <motion.div
117
+ whileHover={{ scale: 1.05 }}
118
+ whileTap={{ scale: 0.95 }}
119
+ whileFocus={{ borderColor: "#3b82f6" }}
120
+ // Drag
121
+ drag // true = x+y, "x" = horizontal only, "y" = vertical only
122
+ dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
123
+ dragElastic={0.2} // 0 = rigid, 1 = free (default 0.35)
124
+ dragSnapToOrigin // returns to initial position
125
+ onDragEnd={(e, info) => {
126
+ if (info.offset.x > 100) handleSwipe("right");
127
+ }}
128
+ />
129
+ ```
130
+
131
+ ## Motion values — Reactive without re-render
132
+
133
+ ```tsx
134
+ const x = useMotionValue(0);
135
+ const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0]);
136
+ const background = useTransform(x, [-200, 200], ["#ff0000", "#00ff00"]);
137
+
138
+ // Spring-based smoothing
139
+ const smoothX = useSpring(x, { stiffness: 300, damping: 30 });
140
+
141
+ // Scroll tracking
142
+ const { scrollY, scrollYProgress } = useScroll();
143
+ const parallaxY = useTransform(scrollYProgress, [0, 1], [0, -300]);
144
+
145
+ // Element-scoped scroll
146
+ const ref = useRef(null);
147
+ const { scrollYProgress } = useScroll({
148
+ target: ref,
149
+ offset: ["start end", "end start"],
150
+ });
151
+ ```
152
+
153
+ **Motion values do NOT trigger React re-renders** — they update the DOM directly via `style`.
154
+
155
+ ## Do Not
156
+
157
+ ### Do not setState in callbacks without a guard
158
+
159
+ ```tsx
160
+ // BAD — infinite re-render if animate depends on state
161
+ onUpdate={(latest) => setPosition(latest.x)}
162
+
163
+ // GOOD — guard or useMotionValueEvent
164
+ const x = useMotionValue(0);
165
+ useMotionValueEvent(x, "change", (latest) => {
166
+ if (latest > threshold) onThresholdReached();
167
+ });
168
+ ```
169
+
170
+ ### Do not use layout animation without a stable key
171
+
172
+ ```tsx
173
+ // BAD — key changes every render, breaks layout tracking
174
+ <motion.div layout key={Math.random()} />
175
+
176
+ // GOOD — stable key derived from data
177
+ <motion.div layout key={item.id} />
178
+ ```
179
+
180
+ ### Do not forget the unique key on AnimatePresence
181
+
182
+ ```tsx
183
+ // BAD — no key, exit animation does not trigger
184
+ <AnimatePresence>
185
+ {isOpen && <motion.div exit={{ opacity: 0 }} />}
186
+ </AnimatePresence>
187
+
188
+ // GOOD — unique key for each conditional child
189
+ <AnimatePresence>
190
+ {isOpen && <motion.div key="modal" exit={{ opacity: 0 }} />}
191
+ </AnimatePresence>
192
+ ```
193
+
194
+ ### Do not wrap an already animated component with motion.div
195
+
196
+ ```tsx
197
+ // BAD — double animation, transform conflicts
198
+ <motion.div animate={{ x: 100 }}>
199
+ <motion.div animate={{ x: -50 }}>Content</motion.div>
200
+ </motion.div>
201
+
202
+ // GOOD — single animation level per transform axis
203
+ <motion.div animate={{ x: 100 }}>
204
+ <motion.div animate={{ opacity: 0.5 }}>Content</motion.div>
205
+ </motion.div>
206
+
207
+ // GOOD — use variants to coordinate parent/child
208
+ <motion.div variants={parent} animate="active">
209
+ <motion.div variants={child} />
210
+ </motion.div>
211
+ ```
212
+
213
+ ## Deep dive
214
+
215
+ | Need | Reference |
216
+ |---|---|
217
+ | Full API reference — motion props (animation, gestures, drag, layout, lifecycle), AnimatePresence modes, transition configuration and ease presets, and the hooks (`useMotionValue`, `useTransform`, `useSpring`, `useScroll`) | `references/api.md` |
218
+
219
+ ## Output
220
+
221
+ The motion-wrapped React component(s) with stable keys, variants where
222
+ parent/child coordinate, and gesture guards — plus the reason Framer
223
+ Motion was the right tier for this effect rather than CSS.