Design System

Motion

Motion exists to explain a change, never to decorate one. It is fast, small in distance, and always optional — a person who asks for reduced motion gets none of it.

What is this?

Four duration tokens (instant, fast, normal, slow), three easing curves (standard, emphasized, linear), and a single ds-transition utility that components apply to interactive state changes.

When to use it

  • State feedback on hover, press and focus
  • Something entering or leaving: menu, dialog, drawer, toast
  • Progress and loading indicators that need continuous motion

How to use it

  • Use fast for hover and press, normal for surfaces entering or leaving
  • Use the standard curve unless a surface needs emphasis on entry
  • Animate transform and opacity — not layout, width or height

What to avoid

  • Animating anything longer than the slow duration
  • Motion that moves content the user is reading
  • Custom keyframes when ds-transition already covers the case

Tokens

Durations and easing curves available as --ds-duration-* and --ds-ease-*.

  • duration-instant
  • duration-fast
  • duration-normal
  • duration-slow
  • ease-standard
  • ease-emphasized
  • ease-linear

What each duration is for

Duration assignment by interaction type.
DurationUse forExample
instantChanges that must feel like direct manipulationCheckbox tick, toggle knob
fastHover, press and focus feedbackButton background, row hover
normalSurfaces entering or leavingPopover, dropdown, toast
slowLarger travel across the viewportDrawer slide, dialog scale-in

Reduced motion

prefers-reduced-motion is honoured globally

Under @media (prefers-reduced-motion: reduce) every duration token collapses to zero, so components change state instantly instead of animating. Nothing is lost: no meaning in this system is carried by motion alone.

If you add a custom animation, it must be defined with a duration token so it inherits this behaviour automatically.

Do & don't

Do

  • Apply the ds-transition utility so timing and easing stay consistent.
  • Keep entry and exit symmetrical — exits may be one step faster.
  • Animate opacity and small transforms only.
  • Let spinners and skeletons carry loading, not page-level animation.

Don't

  • Do not animate colour on large surfaces — it reads as flicker.
  • Do not stagger more than a handful of items.
  • Do not use motion to draw attention to static content.
  • Do not hardcode a millisecond value in a component.

Why it is designed this way

Short, token-driven motion keeps a data-dense product feeling responsive rather than animated. Routing everything through duration tokens is also what makes the reduced-motion contract enforceable: one media query disables the whole system's motion, with no component-by-component audit.