@hegemonart/get-design-done 1.16.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +7 -5
- package/.claude-plugin/plugin.json +17 -5
- package/CHANGELOG.md +84 -0
- package/README.md +20 -2
- package/agents/design-auditor.md +60 -1
- package/agents/design-doc-writer.md +21 -0
- package/agents/design-executor.md +22 -4
- package/agents/design-pattern-mapper.md +61 -0
- package/agents/motion-mapper.md +74 -9
- package/agents/token-mapper.md +8 -0
- package/package.json +10 -2
- package/reference/components/README.md +27 -23
- package/reference/components/alert.md +198 -0
- package/reference/components/badge.md +202 -0
- package/reference/components/breadcrumbs.md +198 -0
- package/reference/components/chip.md +209 -0
- package/reference/components/command-palette.md +228 -0
- package/reference/components/date-picker.md +227 -0
- package/reference/components/file-upload.md +219 -0
- package/reference/components/list.md +217 -0
- package/reference/components/menu.md +212 -0
- package/reference/components/navbar.md +211 -0
- package/reference/components/pagination.md +205 -0
- package/reference/components/progress.md +210 -0
- package/reference/components/rich-text-editor.md +226 -0
- package/reference/components/sidebar.md +211 -0
- package/reference/components/skeleton.md +197 -0
- package/reference/components/slider.md +208 -0
- package/reference/components/stepper.md +220 -0
- package/reference/components/table.md +229 -0
- package/reference/components/toast.md +200 -0
- package/reference/components/tree.md +225 -0
- package/reference/css-grid-layout.md +835 -0
- package/reference/external/NOTICE.hyperframes +28 -0
- package/reference/image-optimization.md +582 -0
- package/reference/motion-advanced.md +754 -0
- package/reference/motion-easings.md +381 -0
- package/reference/motion-interpolate.md +282 -0
- package/reference/motion-spring.md +234 -0
- package/reference/motion-transition-taxonomy.md +155 -0
- package/reference/motion.md +20 -0
- package/reference/output-contracts/motion-map.schema.json +135 -0
- package/reference/registry.json +183 -0
- package/reference/registry.schema.json +4 -0
- package/reference/variable-fonts-loading.md +532 -0
- package/scripts/lib/easings.cjs +280 -0
- package/scripts/lib/parse-contract.cjs +220 -0
- package/scripts/lib/spring.cjs +160 -0
- package/scripts/tests/test-motion-provenance.sh +64 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
<!-- Source: React Native — Libraries/Animated/SpringConfig.js (MIT License) -->
|
|
2
|
+
<!-- Attribution: Facebook, Inc. and its affiliates -->
|
|
3
|
+
|
|
4
|
+
# Motion Springs
|
|
5
|
+
|
|
6
|
+
Spring animations model physical mass-spring-damper systems. Unlike tween animations, springs are driven by physics rather than duration — they respond to velocity and settle naturally, making them ideal for interactions that require a sense of weight.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## The Spring Parameter Triad
|
|
11
|
+
|
|
12
|
+
Every spring is defined by three parameters:
|
|
13
|
+
|
|
14
|
+
### Stiffness (`k`)
|
|
15
|
+
|
|
16
|
+
The spring constant — how strongly the spring pulls toward the target.
|
|
17
|
+
|
|
18
|
+
- **Low stiffness** (80–150): soft, gentle, slow to accelerate
|
|
19
|
+
- **Medium stiffness** (150–300): standard UI feel
|
|
20
|
+
- **High stiffness** (300–600): snappy, responsive, fast
|
|
21
|
+
|
|
22
|
+
Higher stiffness = faster animation, more acceleration. Does not affect whether the spring overshoots.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
### Damping (`c`)
|
|
27
|
+
|
|
28
|
+
The friction coefficient — how quickly oscillation energy is removed.
|
|
29
|
+
|
|
30
|
+
- **Low damping relative to stiffness**: spring oscillates (undershooted)
|
|
31
|
+
- **Damping at critical value**: spring settles exactly without oscillation
|
|
32
|
+
- **High damping**: spring creeps slowly to target (overdamped)
|
|
33
|
+
|
|
34
|
+
Damping controls the *character* of the settle. Lower damping = more bounce.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### Mass (`m`)
|
|
39
|
+
|
|
40
|
+
The simulated mass attached to the spring.
|
|
41
|
+
|
|
42
|
+
- **Low mass** (< 1): snappy, light feel
|
|
43
|
+
- **Mass = 1**: standard (most presets)
|
|
44
|
+
- **High mass** (> 1): heavy, sluggish, long tail
|
|
45
|
+
|
|
46
|
+
Mass scales settle time proportionally. Doubling mass approximately doubles settle time.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Critical Damping Condition
|
|
51
|
+
|
|
52
|
+
A spring is critically damped when:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
c = 2 * sqrt(k * m)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
At this value, the spring reaches its target in minimum time without oscillating. Below this threshold, the spring overshoots. Above it, the spring is overdamped (sluggish).
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
const { criticalDamping } = require('./scripts/lib/spring.cjs');
|
|
62
|
+
|
|
63
|
+
const c = criticalDamping(400, 1); // stiffness=400, mass=1 → c ≈ 40
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Most UI springs use damping *below* the critical value to add character and life to motion.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Canonical Presets
|
|
71
|
+
|
|
72
|
+
### `gentle`
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
stiffness: 120 | damping: 14 | mass: 1
|
|
76
|
+
settle time: ~400ms | overshoots: yes (mild)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
A soft, friendly spring. Overshoots slightly. Good for content reveals, cards expanding, or any motion that should feel unhurried.
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
// Framer Motion
|
|
83
|
+
<motion.div animate={{ y: 0 }} transition={{ type: 'spring', stiffness: 120, damping: 14, mass: 1 }} />
|
|
84
|
+
|
|
85
|
+
// React Spring
|
|
86
|
+
useSpring({ from: { y: -40 }, to: { y: 0 }, config: { tension: 120, friction: 14, mass: 1 } });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### `wobbly`
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
stiffness: 180 | damping: 12 | mass: 1
|
|
95
|
+
settle time: ~600ms | overshoots: yes (pronounced, 2–3 cycles)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
High energy, bouncy. Use for playful or expressive interactions — celebratory states, game-like UIs, avatar reactions. Not appropriate for productivity or enterprise UIs.
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
// Framer Motion
|
|
102
|
+
<motion.div animate={{ scale: 1 }} transition={{ type: 'spring', stiffness: 180, damping: 12, mass: 1 }} />
|
|
103
|
+
|
|
104
|
+
// React Spring
|
|
105
|
+
useSpring({ from: { scale: 0.8 }, to: { scale: 1 }, config: { tension: 180, friction: 12, mass: 1 } });
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### `stiff`
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
stiffness: 400 | damping: 30 | mass: 1
|
|
114
|
+
settle time: ~200ms | overshoots: minimal
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Fast and tight. Feels responsive and precise. Good for small UI elements: toggles, checkboxes, icon state changes, cursor-tracking components. Near-critical damping means it barely overshoots.
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
// Framer Motion
|
|
121
|
+
<motion.div animate={{ opacity: 1 }} transition={{ type: 'spring', stiffness: 400, damping: 30, mass: 1 }} />
|
|
122
|
+
|
|
123
|
+
// React Spring
|
|
124
|
+
useSpring({ from: { opacity: 0 }, to: { opacity: 1 }, config: { tension: 400, friction: 30, mass: 1 } });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### `slow`
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
stiffness: 280 | damping: 60 | mass: 1
|
|
133
|
+
settle time: ~800ms | overshoots: no (overdamped)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Overdamped spring — creeps gently to target with no oscillation. Feels heavy and deliberate. Good for large layout changes, full-screen transitions, onboarding sequences.
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
// Framer Motion
|
|
140
|
+
<motion.div animate={{ x: 0 }} transition={{ type: 'spring', stiffness: 280, damping: 60, mass: 1 }} />
|
|
141
|
+
|
|
142
|
+
// React Spring
|
|
143
|
+
useSpring({ from: { x: -200 }, to: { x: 0 }, config: { tension: 280, friction: 60, mass: 1 } });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Preset Summary Table
|
|
149
|
+
|
|
150
|
+
| Name | Stiffness | Damping | Mass | Settle | Character |
|
|
151
|
+
|---|---|---|---|---|---|
|
|
152
|
+
| `gentle` | 120 | 14 | 1 | ~400ms | Soft, mild overshoot |
|
|
153
|
+
| `wobbly` | 180 | 12 | 1 | ~600ms | Bouncy, 2–3 cycles |
|
|
154
|
+
| `stiff` | 400 | 30 | 1 | ~200ms | Snappy, minimal bounce |
|
|
155
|
+
| `slow` | 280 | 60 | 1 | ~800ms | Heavy, no overshoot |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## CSS `linear()` Approximation
|
|
160
|
+
|
|
161
|
+
CSS does not have a native spring primitive, but the `linear()` timing function (Chrome 113+, Firefox 112+) can approximate a spring by sampling it at many points.
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// scripts/lib/spring.cjs — bake a spring to CSS linear()
|
|
165
|
+
const { step, settleTime } = require('./scripts/lib/spring.cjs');
|
|
166
|
+
|
|
167
|
+
function bakeSpringToCSS(stiffness, damping, mass, samples = 60) {
|
|
168
|
+
const duration = settleTime(stiffness, damping, mass);
|
|
169
|
+
const dt = duration / samples / 1000; // convert ms to seconds
|
|
170
|
+
const points = [];
|
|
171
|
+
|
|
172
|
+
let pos = 0, vel = 0;
|
|
173
|
+
for (let i = 0; i <= samples; i++) {
|
|
174
|
+
points.push(pos.toFixed(4));
|
|
175
|
+
const result = step(stiffness, damping, mass, vel, dt);
|
|
176
|
+
pos = result.position;
|
|
177
|
+
vel = result.velocity;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return `linear(${points.join(', ')})`;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```css
|
|
185
|
+
/* Example output for stiff preset (stiffness=400, damping=30, mass=1) */
|
|
186
|
+
:root {
|
|
187
|
+
--spring-stiff: linear(
|
|
188
|
+
0, 0.081, 0.301, 0.567, 0.789, 0.913, 0.972, 0.997, 1.006,
|
|
189
|
+
1.004, 1.001, 1.000, 1.000 100%
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.toggle {
|
|
194
|
+
transition: transform 200ms var(--spring-stiff);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The baked approximation loses velocity responsiveness (a real spring reacts to initial velocity; a CSS timing function does not), but is acceptable for state-driven transitions.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## When to Use Spring vs Tween
|
|
203
|
+
|
|
204
|
+
### Use spring when:
|
|
205
|
+
|
|
206
|
+
- **Drag release / throw** — the animation should carry the momentum from the gesture. Springs naturally handle initial velocity; tweens cannot.
|
|
207
|
+
- **Toggle state** — a checkbox, switch, or button that needs to feel responsive and alive. The `stiff` preset is standard here.
|
|
208
|
+
- **Interactive hover / follow** — cursor-tracking, magnetic elements. Springs give a sense of physical weight.
|
|
209
|
+
- **Interrupt-safe sequences** — if the user reverses a motion mid-way, springs handle the reversal gracefully by inheriting the current velocity.
|
|
210
|
+
|
|
211
|
+
### Use tween (eased duration) when:
|
|
212
|
+
|
|
213
|
+
- **Navigation transitions** — page or route changes should complete in a fixed, predictable time. A spring may not settle in time if interrupted.
|
|
214
|
+
- **Data-driven state changes** — tab switches, accordion open/close, tooltip appear. A 200–300ms cubic-out tween is predictable and familiar.
|
|
215
|
+
- **Reduced motion** — when `prefers-reduced-motion` is active, replace all springs with short (150ms) linear or ease-out tweens. Springs are inherently bouncy; motion-sensitive users should never see oscillation.
|
|
216
|
+
- **Synchronized choreography** — when multiple elements must start and end together (e.g., a staggered list entrance), tweens with explicit durations are easier to coordinate.
|
|
217
|
+
|
|
218
|
+
```css
|
|
219
|
+
@media (prefers-reduced-motion: reduce) {
|
|
220
|
+
.animated {
|
|
221
|
+
transition-timing-function: var(--ease-linear);
|
|
222
|
+
transition-duration: 150ms;
|
|
223
|
+
/* override any spring-based JS animation via a CSS signal */
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Pairs With
|
|
231
|
+
|
|
232
|
+
- Easing functions for tween-based alternatives: [motion-easings.md](./motion-easings.md)
|
|
233
|
+
- Interpolation for mapping spring output to CSS values: [motion-interpolate.md](./motion-interpolate.md)
|
|
234
|
+
- The `scripts/lib/spring.cjs` module exposes `PRESETS`, `criticalDamping`, `settleTime`, and `step` for programmatic use.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<!-- Source: hyperframes registry/blocks/transitions-* (Apache License 2.0) -->
|
|
2
|
+
<!-- See: reference/external/NOTICE.hyperframes for full attribution -->
|
|
3
|
+
|
|
4
|
+
# Motion Transition Taxonomy
|
|
5
|
+
|
|
6
|
+
Eight controlled transition families derived from the hyperframes registry. Each family describes a distinct visual strategy for moving between UI states. Use this taxonomy to select, name, and constrain transitions consistently across the design system.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 3d
|
|
11
|
+
|
|
12
|
+
The 3d family covers transitions driven by depth and perspective. Elements rotate or flip along a spatial axis so the viewer perceives them moving through three-dimensional space rather than sliding across a flat surface. The visual character is physical and mechanical — content feels like it has mass, faces, and hinge points. Timing curves should emphasize the acceleration and deceleration of a real object rotating under gravity.
|
|
13
|
+
|
|
14
|
+
**Canonical examples:** `flip-x`, `flip-y`, `rotate-3d-left`, `cube-left`
|
|
15
|
+
|
|
16
|
+
### When to use
|
|
17
|
+
|
|
18
|
+
- **Page flips in book or document viewers** — the metaphor of a literal page turning reinforces the reading model.
|
|
19
|
+
- **Card flip interactions** — revealing the back of a card (e.g., a flashcard, a product tile showing detail) benefits from the physical flip metaphor.
|
|
20
|
+
- **Onboarding carousel slides** — a cube or rotating panel transition communicates sequential steps with a stronger sense of progression than a flat slide.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. blur
|
|
25
|
+
|
|
26
|
+
The blur family transitions content by shifting focus: the outgoing element loses sharpness while the incoming element sharpens into clarity. The motion resembles a camera rack-focus — attention narrows onto a single point and then expands to the new content. Unlike most transition families, blur operates in the depth-of-field axis rather than the spatial or temporal axis, making it feel intimate and selective.
|
|
27
|
+
|
|
28
|
+
**Canonical examples:** `blur-in`, `blur-out`, `blur-in-up`, `blur-in-down`
|
|
29
|
+
|
|
30
|
+
### When to use
|
|
31
|
+
|
|
32
|
+
- **Focus-mode overlays** — blurring underlying content when a modal, drawer, or spotlight opens communicates that the rest of the UI has receded.
|
|
33
|
+
- **Photo gallery lightbox opens** — racking focus from thumbnail to full image reinforces the zoom metaphor without a disorienting scale jump.
|
|
34
|
+
- **Loading skeleton to content** — blurring out a skeleton and sharpening in the real content feels more organic than an abrupt swap or a flat cross-fade.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3. cover
|
|
39
|
+
|
|
40
|
+
The cover family uses a fill or wipe that expands from one edge to conceal the outgoing content and simultaneously reveal the incoming content behind it. The transition is directional — left, right, up, or down — giving users a strong spatial cue about where they are navigating. The incoming content is already fully rendered beneath the cover layer, so there is no compositional ambiguity mid-transition.
|
|
41
|
+
|
|
42
|
+
**Canonical examples:** `cover-left`, `cover-right`, `cover-up`, `cover-down`
|
|
43
|
+
|
|
44
|
+
### When to use
|
|
45
|
+
|
|
46
|
+
- **Route transitions in marketing sites** — a cover wipe from the current page edge toward the next reinforces the left-to-right or top-to-bottom navigation model.
|
|
47
|
+
- **Section reveals on scroll** — covering the previous section as the next one rises into view creates a satisfying page-turning rhythm for long-form content.
|
|
48
|
+
- **Slide-panel opens** — a drawer or side panel that covers the main content from its natural edge feels grounded rather than floating.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 4. destruction
|
|
53
|
+
|
|
54
|
+
The destruction family fragments outgoing content before new content appears. Elements shatter, explode, pixelate, or break apart into constituent pieces that scatter or dissolve. The transition is intentionally dramatic and high-entropy — it signals a decisive, irreversible state change rather than a soft navigation event. Because of its visual weight, destruction transitions should be reserved for moments where the drama is earned.
|
|
55
|
+
|
|
56
|
+
**Canonical examples:** `shatter`, `explode`, `pixelate-out`, `break-apart`
|
|
57
|
+
|
|
58
|
+
### When to use
|
|
59
|
+
|
|
60
|
+
- **Onboarding celebrations** — completing a significant setup milestone (connecting an account, finishing a profile) can warrant a brief destruction-style break of the previous step.
|
|
61
|
+
- **Error states (use sparingly)** — a pixelate-out or shatter on a failed action can reinforce the severity of the error without a generic fade, but overuse deadens the signal.
|
|
62
|
+
- **Game-style transitions** — level completions, score reveals, or achievement unlocks in game-adjacent products match the genre conventions users already associate with this visual language.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 5. dissolve
|
|
67
|
+
|
|
68
|
+
The dissolve family cross-fades both the outgoing and incoming content so they overlap during the transition period. Neither element is hidden at the midpoint — the viewer sees a superimposition of both states. This creates a sense of continuity and blending rather than replacement. Dissolves feel gentle and temporal: time is passing, but the context is preserved.
|
|
69
|
+
|
|
70
|
+
**Canonical examples:** `dissolve`, `fade-through-black`, `fade-through-white`, `morph-dissolve`
|
|
71
|
+
|
|
72
|
+
### When to use
|
|
73
|
+
|
|
74
|
+
- **Content replacement where continuity matters** — updating a detail panel or a card's content without navigating away benefits from dissolve so the user understands they are still in the same location.
|
|
75
|
+
- **Photo slideshows** — the classic cross-dissolve between images preserves the sense of a continuous viewing experience.
|
|
76
|
+
- **Wizard step changes** — stepping through a multi-step form where each step occupies the same spatial region reads more clearly with a dissolve than a directional slide, because the user has not navigated anywhere.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 6. distortion
|
|
81
|
+
|
|
82
|
+
The distortion family applies mesh warping, ripple, stretch, or liquid deformation to content during the transition. Rather than moving content spatially or temporally, distortion transitions make the pixels themselves behave like a physical medium — rubber, water, or fabric — that stretches and snaps back. The effect is visceral and tactile. Used well, it adds a signature moment that makes a product feel materially distinct.
|
|
83
|
+
|
|
84
|
+
**Canonical examples:** `warp`, `ripple`, `stretch-in`, `liquid`
|
|
85
|
+
|
|
86
|
+
### When to use
|
|
87
|
+
|
|
88
|
+
- **Creative and editorial contexts** — design portfolios, editorial publications, and art-directed landing pages where differentiation is a primary goal.
|
|
89
|
+
- **Unique brand moments** — a single, well-timed warp or ripple on a hero image transition can become a brand signature without overwhelming the interface.
|
|
90
|
+
- **Hero section transitions on marketing sites** — distortion applied at the seam between a full-bleed hero and the next section creates a visceral scroll reward that flat transitions cannot match.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 7. grid
|
|
95
|
+
|
|
96
|
+
The grid family breaks content into a regular matrix of tiles that animate independently — entering, exiting, flipping, or fading in a choreographed sequence. The grid subdivision can be dense (many small tiles for a mosaic effect) or coarse (a few large panels). The transition communicates that the content is composed of discrete pieces, which suits imagery and portfolio work where the grid metaphor is already meaningful.
|
|
97
|
+
|
|
98
|
+
**Canonical examples:** `grid-in`, `grid-out`, `checkerboard`, `tile-flip`
|
|
99
|
+
|
|
100
|
+
### When to use
|
|
101
|
+
|
|
102
|
+
- **Portfolio galleries** — revealing a new set of work by animating each thumbnail cell independently reinforces the gallery grid metaphor.
|
|
103
|
+
- **Image reveals** — a grid-in where tiles appear in a wave pattern draws the eye across the composition before the full image settles.
|
|
104
|
+
- **Dramatic content transitions in editorial contexts** — a checkerboard or tile-flip between major sections of an editorial layout creates a theatrical reveal suited to magazine-style layouts.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 8. light
|
|
109
|
+
|
|
110
|
+
The light family uses luminosity effects — flash, glow, lens flare, or bloom — to punctuate the moment of transition. Rather than moving content spatially, light transitions overwhelm the frame briefly with brightness or radiant energy before the new content resolves. The effect is momentary and climactic, borrowed from cinematic language where a burst of light signals a revelation, a completion, or the passage of significance.
|
|
111
|
+
|
|
112
|
+
**Canonical examples:** `flash`, `whiteout`, `bloom`, `lens-flare`
|
|
113
|
+
|
|
114
|
+
### When to use
|
|
115
|
+
|
|
116
|
+
- **Onboarding completions** — a flash or bloom when the user finishes setup signals that something important has happened.
|
|
117
|
+
- **Achievement unlocks** — reward moments in any product (reaching a milestone, earning a badge) suit light transitions because brightness is universally read as positive and celebratory.
|
|
118
|
+
- **Brand-moment animations and moments of delight** — a subtle lens-flare or glow on a signature interaction (e.g., hitting a streak, confirming a purchase) adds warmth without disrupting flow.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Choosing a Family
|
|
123
|
+
|
|
124
|
+
Quick-reference guide for selecting the right transition family based on visual weight and primary use context.
|
|
125
|
+
|
|
126
|
+
| Family | Visual Weight | Best For |
|
|
127
|
+
|-------------|--------------|--------------------------------------------------|
|
|
128
|
+
| 3d | Medium–Heavy | Physical metaphors, card reveals, sequential steps |
|
|
129
|
+
| blur | Light–Medium | Focus shifts, depth cues, content materialising |
|
|
130
|
+
| cover | Light–Medium | Directional navigation, drawer/panel opens |
|
|
131
|
+
| destruction | Heavy | Celebratory moments, dramatic state changes |
|
|
132
|
+
| dissolve | Light | Soft content replacement, continuity of place |
|
|
133
|
+
| distortion | Medium–Heavy | Brand signatures, editorial hero moments |
|
|
134
|
+
| grid | Medium | Gallery reveals, tile-based image layouts |
|
|
135
|
+
| light | Medium–Heavy | Reward moments, completions, delight beats |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Combining with Duration Classes
|
|
140
|
+
|
|
141
|
+
Transition family choice constrains the appropriate duration range. The duration system (defined in `reference/motion.md`) maps timing to semantic classes: narrative, slow, standard, quick, and instant.
|
|
142
|
+
|
|
143
|
+
**3d and destruction** require slow-to-narrative durations (400–700 ms). Their visual complexity — rotating geometry, fragmenting particles — needs time to resolve clearly. At quick durations they read as broken or glitchy rather than intentional.
|
|
144
|
+
|
|
145
|
+
**distortion** works best in the slow-to-standard range (300–500 ms). Warping too fast looks like an artifact; too slow it becomes self-indulgent. The sweet spot is long enough to feel physical but short enough to feel responsive.
|
|
146
|
+
|
|
147
|
+
**grid** tolerates a wider range depending on tile count. Coarse grids (2×2 or 3×3) can run at standard (200–300 ms); dense mosaics need slow (350–500 ms) so individual tile motion is legible.
|
|
148
|
+
|
|
149
|
+
**light** transitions are typically the shortest of the heavy-weight families. A flash or whiteout at 150–250 ms (standard-to-quick) feels like a camera flash — instantaneous and climactic. Extending it past 400 ms turns a flash into a fade.
|
|
150
|
+
|
|
151
|
+
**dissolve and cover** are the workhorses of the system. Both operate comfortably at standard (200–300 ms) and can be compressed to quick (100–150 ms) for secondary navigation without losing legibility. They are the default choice when in doubt.
|
|
152
|
+
|
|
153
|
+
**blur** sits in the quick-to-standard range (150–300 ms). Longer blur transitions feel like a loading state rather than a deliberate motion.
|
|
154
|
+
|
|
155
|
+
When stacking a transition family choice against the rest of the design: if the moment warrants narrative pacing (slow, deliberate), reach for 3d, destruction, or distortion. If the moment should feel effortless and recede from attention, dissolve and cover at quick or standard are correct. Blur is the right default for focus-management transitions at any speed.
|
package/reference/motion.md
CHANGED
|
@@ -385,3 +385,23 @@ Remove `will-change` after the animation completes if applied dynamically:
|
|
|
385
385
|
```js
|
|
386
386
|
element.addEventListener('transitionend', () => element.style.willChange = 'auto')
|
|
387
387
|
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Advanced Patterns
|
|
392
|
+
|
|
393
|
+
For spring physics, scroll-driven animation, FLIP, View Transitions API, gesture & drag mechanics, clip-path animation patterns, blur-to-mask crossfades, WAAPI, Framer Motion hardware-acceleration gotcha, motion cohesion & personality, and the next-day slow-motion review process, see:
|
|
394
|
+
|
|
395
|
+
→ **`reference/motion-advanced.md`** (Phase 18)
|
|
396
|
+
|
|
397
|
+
For the canonical easing catalog (`--ease-*` tokens, cubic-bezier equivalents, 60fps settle-times):
|
|
398
|
+
|
|
399
|
+
→ **`reference/motion-easings.md`** (Phase 18)
|
|
400
|
+
|
|
401
|
+
For spring parameter presets (gentle / wobbly / stiff / slow):
|
|
402
|
+
|
|
403
|
+
→ **`reference/motion-spring.md`** (Phase 18)
|
|
404
|
+
|
|
405
|
+
For transition family taxonomy (8 families: 3d / blur / cover / destruction / dissolve / distortion / grid / light):
|
|
406
|
+
|
|
407
|
+
→ **`reference/motion-transition-taxonomy.md`** (Phase 18)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "motion-map.schema.json",
|
|
4
|
+
"title": "Motion Map Output Contract",
|
|
5
|
+
"description": "Schema for the structured JSON block emitted by motion-mapper at the top of .design/map/motion.md. Every detected animation binding must conform to this schema.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schema_version", "generated_at", "animations"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema_version": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"const": "1.0.0",
|
|
13
|
+
"description": "Schema version — bump when adding required fields"
|
|
14
|
+
},
|
|
15
|
+
"generated_at": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"format": "date-time",
|
|
18
|
+
"description": "ISO-8601 timestamp of when this map was generated"
|
|
19
|
+
},
|
|
20
|
+
"summary": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"description": "Aggregate counts for quick review",
|
|
23
|
+
"properties": {
|
|
24
|
+
"total_animations": { "type": "integer", "minimum": 0 },
|
|
25
|
+
"custom_easings": { "type": "integer", "minimum": 0 },
|
|
26
|
+
"reduced_motion_compliant": { "type": "boolean" },
|
|
27
|
+
"libraries": {
|
|
28
|
+
"type": "array",
|
|
29
|
+
"items": { "type": "string" },
|
|
30
|
+
"description": "Animation libraries detected (e.g., framer-motion, gsap, css-only)"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"animations": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"description": "One entry per detected animation binding",
|
|
37
|
+
"items": {
|
|
38
|
+
"$ref": "#/definitions/AnimationBinding"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"definitions": {
|
|
43
|
+
"AnimationBinding": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"required": ["id", "location", "easing", "duration_class", "trigger"],
|
|
46
|
+
"additionalProperties": false,
|
|
47
|
+
"properties": {
|
|
48
|
+
"id": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"description": "Unique identifier for this binding, e.g., 'toast-enter-opacity'"
|
|
51
|
+
},
|
|
52
|
+
"location": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"required": ["file", "line"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"file": { "type": "string", "description": "Relative path from project root" },
|
|
57
|
+
"line": { "type": "integer", "minimum": 1 }
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"description": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Human-readable description of what this animation does"
|
|
63
|
+
},
|
|
64
|
+
"easing": {
|
|
65
|
+
"oneOf": [
|
|
66
|
+
{
|
|
67
|
+
"type": "string",
|
|
68
|
+
"enum": [
|
|
69
|
+
"linear",
|
|
70
|
+
"quad", "quad-in", "quad-out", "quad-in-out",
|
|
71
|
+
"cubic", "cubic-in", "cubic-out", "cubic-in-out",
|
|
72
|
+
"poly", "poly-in", "poly-out", "poly-in-out",
|
|
73
|
+
"sin", "sin-in", "sin-out", "sin-in-out",
|
|
74
|
+
"circle", "circle-in", "circle-out", "circle-in-out",
|
|
75
|
+
"exp", "exp-in", "exp-out", "exp-in-out",
|
|
76
|
+
"elastic", "elastic-in", "elastic-out", "elastic-in-out",
|
|
77
|
+
"back", "back-in", "back-out", "back-in-out",
|
|
78
|
+
"bounce", "bounce-in", "bounce-out", "bounce-in-out",
|
|
79
|
+
"bezier"
|
|
80
|
+
],
|
|
81
|
+
"description": "One of the 12 canonical easing presets from reference/motion-easings.md"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"type": "object",
|
|
85
|
+
"required": ["type", "justification"],
|
|
86
|
+
"properties": {
|
|
87
|
+
"type": { "type": "string", "const": "custom" },
|
|
88
|
+
"value": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "The actual easing value (cubic-bezier string, spring config, etc.)"
|
|
91
|
+
},
|
|
92
|
+
"justification": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Why a canonical easing was not sufficient. Must be non-empty."
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"transition_family": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"enum": ["3d", "blur", "cover", "destruction", "dissolve", "distortion", "grid", "light"],
|
|
103
|
+
"description": "Optional: one of the 8 transition families from reference/motion-transition-taxonomy.md. Omit for micro-interactions where no family applies."
|
|
104
|
+
},
|
|
105
|
+
"duration_class": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"enum": ["instant", "quick", "standard", "slow", "narrative"],
|
|
108
|
+
"description": "Duration classification. instant: <100ms, quick: 100-200ms, standard: 200-400ms, slow: 400-800ms, narrative: >800ms"
|
|
109
|
+
},
|
|
110
|
+
"duration_ms": {
|
|
111
|
+
"type": "integer",
|
|
112
|
+
"minimum": 0,
|
|
113
|
+
"description": "Actual duration in milliseconds, if known"
|
|
114
|
+
},
|
|
115
|
+
"trigger": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"enum": ["user-gesture", "state-change", "scroll-progress", "time", "loop"],
|
|
118
|
+
"description": "What drives this animation"
|
|
119
|
+
},
|
|
120
|
+
"reduced_motion_handled": {
|
|
121
|
+
"type": "boolean",
|
|
122
|
+
"description": "Whether this animation respects prefers-reduced-motion"
|
|
123
|
+
},
|
|
124
|
+
"library": {
|
|
125
|
+
"type": "string",
|
|
126
|
+
"description": "Animation library used, e.g., 'framer-motion', 'gsap', 'css-transition', 'waapi'"
|
|
127
|
+
},
|
|
128
|
+
"notes": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"description": "Optional free-form notes for the reviewer"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|