The scale
| Token | Value | Use |
|---|---|---|
--motion-fast | 120ms | Hover and press feedback. The change is small, so the response reads as instant. |
--motion-base | 200ms | Reveals, toggles, small movement. The default. |
--motion-slow | 300ms | Large surfaces: sheets, drawers, whole panels. Also the MOT-1 ceiling for interface motion. |
--motion-story | 600ms | Narrative surfaces only — explanatory diagrams and the landing reveal. Never task UI. |
--motion-fast120ms
--motion-base200ms
--motion-slow300ms
--motion-story600ms
Duration follows the size of the change: the bigger the surface, the longer it may take. If you mirror the tokens in JS for a motion library, keep both in sync.
Easing
| Token | Curve | Use |
|---|---|---|
--ease-out | cubic-bezier(0.215, 0.61, 0.355, 1) | Elements entering or exiting: reveals, dropdowns, tooltips. Starts fast, settles into place. |
--ease-in-out | cubic-bezier(0.645, 0.045, 0.355, 1) | Elements already on screen that move or morph. |
plain ease | browser default | Hover tint changes. |
No bounce or overshoot, ever (SLP-8).
When not to animate
- Anything a person uses 100+ times a day gets no animation. Frequency beats delight: the fiftieth slide-in is friction, not polish.
- Keyboard navigation is always instant. Animation gives pointer interactions spatial feedback; a keyboard user already knows where they are going.
- Paired elements share one duration and one easing. A sheet and its backdrop move as one unit, or they read as two things.
Reduced motion
Every animated surface provides a reduced-motion variant (A11Y-5). In
components that use motion/react, test useReducedMotion() === true: the strict
comparison means the null it returns before hydration never skips the
animation. In CSS, use the motion-reduce: utilities. Turning motion off may
remove emphasis, never meaning: states, order, and relationships stay legible
statically (MOT-3).
The standards
- MOT-1 — interface motion is 100–300ms with standard easing; no decorative motion on critical paths.
- MOT-2 ⚑ — motion values come from this token set; durations and easings are never hardcoded in component code.
- MOT-3 ⚑ — motion may emphasise meaning but never carry it alone; the surface communicates the same information with animations off.
Usage
{/* CSS: duration and easing from tokens */}
<div className="transition-colors duration-(--motion-fast)" />
{/* motion/react, via a JS mirror of the CSS tokens */}
transition={{ duration: DUR.base, ease: EASE_OUT }}Best practices
- DoTake durations and easings from the motion token set (MOT-2).
- DoKeep interface motion at 300ms or less (MOT-1).
- DoGive every animated surface a reduced-motion variant (A11Y-5).
- Don'tHardcode a duration or easing in component code.
- Don'tUse bounce or overshoot easing (SLP-8).