Motion
Sets durations, easing, and reduced motion for every transition.
Principles
- Move only to explain a change. Motion shows where something came from or went, so leave out bounces. Only a progress indicator loops, while its work runs.
- Keep transitions short. Durations here run 120–360ms, and dialogs and toasts close at once.
- Never make input wait. Focus, state, and results change at once, and motion only follows them.
- Change a theme as one scene. The whole screen fades together, so no border or icon trails behind.
- Honor reduced motion. With prefers-reduced-motion, movement stops and every path still works (WCAG 2.3.3).
Motion tokens
Name these tokens instead of writing milliseconds. The values are read live from the current theme.
Reduced motion turns component transitions off but leaves these values as they are.
Component transitions
Each component enters with its own timing and closes without making the reader wait. Sheet and Drawer slide both ways, because where they go matters.
Open the shared Dialog and Sheet, and change the theme while one is open. The draft and focus stay.
Toast and Drawer own their swipe, timing, and pause, so don't rebuild them with timers. Never announce a result on transitionend.
Theme transition
transitionTheme applies the theme attribute and the framework state in one update. With View Transitions, the new screen fades in over the old one for --surf-theme-transition-duration. Without them, the theme applies at once.
- Resolved theme:
- Reduced motion: No preference
- View Transitions API: Unavailable
Call it once per user action, with no timers of your own. Choosing, saving, and restoring a theme belong to Themes.
Reduced motion
- Under
prefers-reduced-motion, dialogs, panels, and the theme change without movement. - Opening, closing, focus return, and announcements work the same, since none of them wait on motion.
- Give a pause control to motion that runs over 5 seconds, such as auto-scroll (WCAG 2.2.2). Never flash more than 3 times a second (WCAG 2.3.1).
W3C C39 — prefers-reduced-motion / Base UI — animation lifecycle
Easing lab
Duration is the total time, and easing spreads progress over it. On the curve, time runs across and progress runs up.
linear, Motion preview enabled
Time 0% / Progress 0.0%
Ready
To read cubic-bezier(x1, y1, x2, y2), find time x on the curve and take its y as progress. A steep slope means fast change.
The system's curves never overshoot. 600ms is a slow preview, not a default.