Animation here is a tool, not decoration. Every motion in the system has to earn its place against four principles, and if it fails any one of them, it gets removed. The thread running through all of it is restraint: short durations, consistent easing, and an absolute respect for players who’ve asked their device to calm motion down.
Purposeful
Every animation communicates a state change, guides attention, or gives feedback.
Test Can you explain why it animates? If not, make it instant.
Fast
Users never wait for an animation to finish before they can act.
Test Does it block interaction? If yes, shorten or remove it.
Accessible
Animations respect the reduced-motion setting, and no content hides behind motion.
Test Does the page work identically with all motion off?
Consistent
The same interaction produces the same motion everywhere.
Test Could a user predict it from other parts of the UI?
The duration scale
Timing is a fixed scale, not a per-component guess. Micro-interactions are tight — a hover at 150ms, a panel at the 250ms base — and nothing runs past a second. Anything that needs longer is broken into staggered steps instead.
| Token | Duration | Use for |
|---|---|---|
xs | 100ms | Button press, instant feedback |
sm | 150ms | Hover states, toggles, micro-interactions |
md | 250–300ms | Modals, panels, drawers, tab switches |
lg | 500ms | Page transitions, complex reveals |
xl | 800ms | Data visualizations, chart entrances |
Micro-interactions above 200ms feel sluggish — keep them tight. And exit animations are always shorter than entrances: exit equals roughly 75% of the entrance duration, so things leave a little quicker than they arrive.
Easing curves
Easing is what gives motion its character, and Playbook never uses the CSS default
ease — it’s too generic and feels inconsistent across components. Instead, five
named curves map to five intentions: things arriving decelerate, things leaving accelerate, and
interactive feedback gets a subtle spring.
| Context | Curve | cubic-bezier | When |
|---|---|---|---|
| Entrance | Ease-out (decelerate) | cubic-bezier(0, 0, 0.2, 1) | Elements arriving — modals, toasts, page content |
| Exit | Ease-in (accelerate) | cubic-bezier(0.4, 0, 1, 1) | Elements leaving — closing modals, dismissing toasts |
| Interactive | Spring | cubic-bezier(0.34, 1.56, 0.64, 1) | Toggles, button press/release, selection pops |
| Two-way | Ease-in-out | cubic-bezier(0.4, 0, 0.2, 1) | Smooth transitions — tab underlines, slider thumbs |
| Progress | Linear | linear | Progress bars, loading indicators, countdowns |
Entrance & exit patterns
Five patterns cover almost everything. Each pairs an entrance with an exit and stays within deliberately small bounds — slides translate no more than 24px, scales stay between 0.95 and 1.05 — so motion reads as polish rather than spectacle.
Fade
Opacity transition — the simplest and most accessible pattern.
Use for Overlays, backdrops, tooltips, popovers, in-place content.
Slide
Small translate (8–24px max) that implies where something comes from.
Use for Side panels, drawers, nav menus, mobile sheets, toasts.
Scale
Transform scale, kept tight to 0.95–1.05 so it never looks cartoonish.
Use for Button press, card hover lift, modal entrance, popovers.
Stagger
50ms between items, capped at 5 — the rest appear instantly.
Use for Card grids, list items, dashboard widgets, quiz options.
For progressive disclosure — accordions, expandable details, FAQ sections — the system animates
grid-template-rows from 0fr to 1fr rather than animating
height or max-height directly. That keeps the collapse
GPU-composited and layout-stable. Component motion follows from these primitives: a card lifts
2px on hover, a modal backdrop fades while its panel scales from 0.95 to 1, and a toast slides
in from the right (or from the bottom on mobile).
For page-level loading, use skeleton placeholders shaped like the content they replace, with a left-to-right shimmer — never a full-page spinner. Spinners are reserved for small, self-contained actions like a button submission or saving a preference. As content streams in, fade each section as it arrives rather than waiting for everything at once.
The reduced-motion rule
This is the non-negotiable of the entire system. Every Playbook implementation must honor the operating system’s reduced-motion preference — it is not optional and it is not a nice-to-have.
When a player has asked their device to reduce motion, every transform and transition collapses to near-instant. Slides and scales land in their final position immediately, fades complete in under a millisecond, and content is visible right away. Crucially, nothing is ever hidden or made unreachable because an animation didn’t run — the page works identically with all motion off.
The same accessibility discipline extends beyond that one media query:
- No content behind animation. Everything must be readable and interactive even if animations never run.
- No autoplay. Looping animations don’t start without user action — the skeleton shimmer is the only exception, because it’s a loading indicator, not decoration.
- No flashing. Nothing flashes more than three times per second — a hard WCAG 2.3.1 requirement.
- No motion-sickness triggers. No parallax scrolling, no zooming transitions, no rotation animations.
- Pause controls. Any looping element — a carousel, rotating tips — needs a visible pause or stop button, and auto-advancing content must allow enough reading time.
On support, self-exclusion, and helpline pages, the motion language softens: spring easing is replaced with ease-in-out, slides become plain fades, scale effects disappear, and durations stretch a little. No confetti, bounces, or pops — and helpline numbers appear immediately, never behind a stagger. This mirrors the warmer register in Voice & Tone.
Dark mode
Dark mode isn’t an inverted light mode — it requires intentional color mapping to keep readability, hierarchy, and brand identity intact. The default behavior is to auto-switch on the system’s dark preference and to persist an explicit in-app toggle. The one firm rule: never force dark mode, and always respect the system preference unless the user has chosen otherwise in the app.
Semantic color mapping
Each token has a deliberate dark-mode value, and every pairing is verified against WCAG 2.1 AA contrast on the dark background. Notably, links and the secondary CTA shift to the brighter teal on dark, while accents move to the lighter orange.
| Token | Light mode | Dark mode | Ratio on dark |
|---|---|---|---|
| Background | neutral-50 #F5F5FA | neutral-900 #1A1A2E | — |
| Surface | white #FFFFFF | neutral-700 #3D3D5C | — |
| Text primary | neutral-900 #1A1A2E | neutral-50 #F5F5FA | 15.70:1 |
| Text secondary | neutral-700 #3D3D5C | neutral-300 #A8A8C0 | 7.33:1 |
| Link | navy #2A3F56 | teal #00D4AA | 8.93:1 |
| Accent (CTA) | orange #FF6B35 | orange-light #FF8A5C | 7.34:1 |
Success, warning, danger, and info always use dark text on their chromatic backgrounds, in light and dark mode — never white text on those colors. Muted text (neutral-500) is the one trap in dark mode: at 3.33:1 it passes for large text only, so use it sparingly and only at 18px+ or 14px+ bold.
Image & media treatment
Imagery needs its own adjustments so nothing glares or bleeds on a dark surface. The most important is dimming photographs slightly; SVG logos and the brand gradient bar need no change.
| Asset type | Dark-mode treatment |
|---|---|
| Photographs | Reduce brightness to 85–90% to prevent glare on dark backgrounds. |
| Illustrations / icons | Use light-on-dark variants — swap stroke and fill colors. |
| Charts / data viz | Light text and gridlines; reduce opacity of non-essential elements. |
| Screenshots | Add a subtle 1px border so edges don’t bleed into the background. |
| Brand gradient bar | No change — the orange-to-teal gradient works on both light and dark. |
Support pages always render in light mode regardless of the system setting — dark mode can feel isolating in a crisis context. When the theme does change, the transition itself is gentle: a 150ms ease-out fade on background and text color, which is exactly the kind of purposeful, fast motion the rest of this page describes.
Motion and dark mode are the finishing layer of the design system. Both report to the brand book’s visual integration test — place the work beside the operator’s commercial content and ask whether it belongs. For the tokens these rules build on, see Color, and for the stroke language the animated charts inherit, see Iconography.