Relay design system

Motion

Eighteen moments, and every one is playable. Nothing on this page runs on its own: press Play and the moment runs on the left as designed and on the right as it runs for someone who has asked for less motion. Most reduced variants read “instant, but the colour cue stays”, because colour is not motion.

Curves, springs and durations are tokens, and no component may write its own. The values are on Foundations; what they are used for is below.

700 ms
No interaction runs longer. The wash and the aurora fade slower, and block nothing.
0 loops
Nothing repeats except the all-clear aurora.
0 pulses
Nothing pulses. A pulsing countdown across a nine-hour shift is torture.
User first
Nothing moves while the hero is being read unless the reader caused it.
M1

Row hover

Full

Order 4821↵

Reduced

Order 4821↵
Trigger
Pointer enters a row
What moves
Row background steps from surface-1 to surface-2. The action cluster fades in and slides 6px.
Timing
90 background · 140 cluster
Easing
ease-out
Stagger
None
Reduced
Background only. No slide.
Avoid
Layout shift. The cluster's track is always reserved.
Built in
components/relay/queue-row.tsx
This stage is a miniature built from the same tokens.
M2

Row focus

Full

Order 48210 ms

Reduced

Order 48210 ms
Trigger
Keyboard focus lands on a row
What moves
A 2px ring at 2px offset, drawn with box-shadow, plus the hover background.
Timing
0 — instant
Easing
None
Stagger
None
Reduced
Identical.
Avoid
Animating the ring in. It must be there on the frame the key lands.
Built in
components/ui/sizing.ts (FOCUS)
This stage is a miniature built from the same tokens.
M3

Press

Full

scale 0.985 · 80 down · 120 up

Reduced

no scale

Trigger
Pointer goes down on a button
What moves
The button scales to 0.985. Only buttons scale, never a row.
Timing
80 down · 120 up
Easing
ease-out
Stagger
None
Reduced
None.
Avoid
Scaling a 64px row instead of the button.
Built in
components/ui/button.tsx
This stage is a miniature built from the same tokens.
M4

Mark donethe signature

Full

Label printer offline
  • Order 4821 payment
  • Reply to vendor
  • Rush order 4796
2 of 12 done

Reduced

Label printer offline
  • Order 4821 payment
  • Reply to vendor
  • Rush order 4796
2 of 12 done
Trigger
Click, Enter or ⌘↵ on the primary action
What moves
The check draws. The hero leaves. The next row lifts out of the list and becomes the hero. The gap closes. The counter rolls. The toast arrives.
Timing
≈700 end to end
Easing
ease-out, spring-layout
Stagger
24ms per row, capped at 5
Reduced
The check, the promotion and the roll become instant. The toast fades in over 120ms.
Avoid
Blocking input during the sequence. Re-running the tint wash on rows that did not move.
Built in
components/relay/hero.tsx · queue.tsx · check-draw.tsx
This stage is a miniature built from the same tokens.
M5

Undo

Full

Rank 1
Label printer

Reduced

Rank 1
Label printer
Trigger
Undo in the toast, or ⌘Z
What moves
The item flies from the toast back to its rank. The hero restores with a crossfade.
Timing
≈420
Easing
spring-layout
Stagger
None
Reduced
Instant.
Avoid
Playing Mark done backwards. It reads as a glitch. Undo is one move, not a rewind.
Built in
components/relay/undo-toast.tsx · hero.tsx
This stage is a miniature built from the same tokens.
M6

Undo toast

Full

220 in · holds 8 s (2.4 s here) · 160 out

Reduced

fade · holds 12 s (2.4 s here)

Trigger
After Mark done
What moves
Enters from the bottom-left, 8px up and fading in. 56px tall, 360px wide. Holds 8s, then leaves.
Timing
220 in · 160 out
Easing
ease-out in, ease-in out
Stagger
None
Reduced
Fade only. Holds 12s.
Avoid
Landing over the top bar's search field, or a sub-44px Undo target.
Built in
components/ui/toast.tsx · components/relay/toast-bridge.tsx
This stage runs the shipped component.
M7

Countdown

Full

One step a minute

Reduced

One step a minute

Trigger
Each simulated minute
What moves
The digits roll. The arc advances one step. At 15 minutes left the arc shifts to the Act-now hue, once.
Timing
320 roll · 600 hue
Easing
ease-in-out
Stagger
None
Reduced
Digits swap. The arc steps each minute. No hue transition.
Avoid
Pulsing. Nothing on this screen may pulse.
Built in
components/relay/countdown-arc.tsx
This stage is a miniature built from the same tokens.
M8

Tier re-sort

Full

  • Order 4821
  • Vendor reply
  • Rush 4796
  • Count C4

Reduced

  • Order 4821
  • Vendor reply
  • Rush 4796
  • Count C4
Trigger
A score changes
What moves
Rows whose index changed reposition. The moved row gets a tint that fades to nothing so the eye can find it.
Timing
spring-layout · 900 wash
Easing
spring-layout
Stagger
24ms
Reduced
Positions jump. The wash stays, because it is colour and not motion.
Avoid
Animating every row when one moved.
Built in
components/relay/queue.tsx · app/globals.css (.tint-wash)
This stage is a miniature built from the same tokens.
M9

New urgent item

Full

Label printer offline

140 orders wait on it

Reduced

Label printer offline

140 orders wait on it

Trigger
A higher-ranked item arrives
What moves
A 48px band slides down inside the hero. The band's border runs one light sweep, left to right.
Timing
260 slide · 700 sweep, once
Easing
ease-out
Stagger
None
Reduced
The band fades in. No sweep.
Avoid
Repeating the sweep. Once per arrival, ever.
Built in
components/relay/new-urgent-band.tsx
This stage runs the shipped component.
M10

Why is this first?

Full

Time
Blocked
Impact
Total

Reduced

Time
Blocked
Impact
Total
Trigger
Click the link
What moves
The panel scales from 0.96 out of the link's own corner. The four weight bars fill left to right.
Timing
180 panel · 240 bars
Easing
ease-out
Stagger
50ms per bar
Reduced
Bars render filled. The panel fades over 120ms.
Avoid
Bars that animate on every re-open. Animate on the first open per item only.
Built in
components/relay/why-popover.tsx · why-factors.tsx
This stage is a miniature built from the same tokens.
M11

Right sheet

Full

  • Order 4821
  • Vendor reply
  • Rush 4796

Reduced

  • Order 4821
  • Vendor reply
  • Rush 4796
Trigger
Row click, or Enter
What moves
The panel slides 24px in from the right and fades in. Its sections follow one after another.
Timing
spring-sheet ≈520
Easing
spring-sheet
Stagger
28ms per section, 4 max
Reduced
A 140ms fade.
Avoid
A sheet that covers the row that opened it. The scrim dims, and the source row stays visible at 1440.
Built in
components/relay/item-detail-sheet.tsx
This stage is a miniature built from the same tokens.
M12

Bottom sheet

Full

Reduced

Trigger
Tap, at 390
What moves
The sheet rises and snaps at 55% or 94% of the screen.
Timing
spring-sheet
Easing
spring-sheet
Stagger
None
Reduced
A fade.
Avoid
Rubber-banding past 94%.
Built in
components/relay/item-detail-sheet.tsx (Vaul)
This stage is a miniature built from the same tokens.
M13

Command palette

Full

Reduced

Trigger
⌘K
What moves
The scrim fades in and blurs. The panel scales from 0.97. The selection highlight glides between rows.
Timing
160 scrim · 200 panel · 120 highlight
Easing
ease-in-out
Stagger
None
Reduced
No blur. The highlight jumps.
Avoid
Blurring the whole app. Blur the scrim layer only, never the page.
Built in
components/relay/command-palette.tsx
This stage is a miniature built from the same tokens.
M14

Theme switch

Full

Label printer offline

Reveal grows from the toggle

Reduced

Label printer offline

Reveal grows from the toggle

Trigger
The mode toggle
What moves
A circular reveal grows from the toggle's centre until it covers the page.
Timing
420
Easing
ease-in-out
Stagger
None
Reduced
Instant swap. No transition.
Avoid
Running the reveal on first paint.
Built in
lib/theme-transition.ts
This stage is a miniature built from the same tokens.
M15

Tabs

Full

For you updates

Reduced

For you updates
Trigger
Click a tab
What moves
The active pill glides to the new tab. The label does not move.
Timing
200
Easing
ease-in-out
Stagger
None
Reduced
The pill jumps.
Avoid
Animating the label text along with the pill.
Built in
components/relay/update-tabs.tsx
This stage runs the shipped component.
M16

Skeleton to content

Full

  • Order 4821 payment
  • Reply to vendor
  • Rush order 4796

Reduced

  • Order 4821 payment
  • Reply to vendor
  • Rush order 4796
Trigger
Data is ready
What moves
The blocks crossfade to the content. No shimmer.
Timing
180
Easing
ease-out
Stagger
30ms per row, 6 max
Reduced
Instant.
Avoid
A shimmer loop. The data resolves in under 50ms, and a shimmer lies about latency.
Built in
components/ui/skeleton.tsx
This stage runs the shipped component.
M17

All clear

Full

You are clear until 13:00

  • Label printer10:10
  • Order 482110:17
  • Vendor reply10:24

Reduced

You are clear until 13:00

  • Label printer10:10
  • Order 482110:17
  • Vendor reply10:24
Trigger
The queue empties
What moves
The aurora fades in. The headline rises 12px behind it. Today's list steps up one line at a time.
Timing
900 aurora · 420 headline
Easing
ease-out
Stagger
40ms per item, 8 max
Reduced
The aurora is static. The headline fades over 160ms.
Avoid
Confetti. Never confetti in a workplace tool.
Built in
components/relay/all-clear.tsx
This stage is a miniature built from the same tokens.
M18

Count change

Full

Up next3

Reduced

Up next3
Trigger
A tile or tier count changes
What moves
The number rolls. On an increase only, the band's hairline flashes to line-2 and back.
Timing
320 roll · 500 flash
Easing
ease-out
Stagger
None
Reduced
The number swaps. The flash stays.
Avoid
Flashing on a decrease. A decreasing count is good news.
Built in
components/relay/risk-tile.tsx · queue.tsx
This stage is a miniature built from the same tokens.