Motion
How the components move, what reduced motion changes, and the contracts behind gestures, shared elements and scrolling.
Tokens
Transitions read role-named tokens: ease-gesture, ease-emphasized,
ease-emphasized-soft and ease-indicator, with their durations. Everything else
uses Tailwind's ease-out / ease-in and its numeric duration scale. To change
them, see Theming → Motion.
Reduced motion
Under prefers-reduced-motion: reduce:
- Movement transitions stop, and the change still happens. A sheet appears in place, a dialog appears without zooming, BottomNav's indicator jumps to the new item.
- Colour transitions stay. WCAG does not count a colour change as motion, and a fade is what replaces motion rather than another thing to remove.
- Direct manipulation stays. A sheet still follows a dragging finger, and a swipe still dismisses it: the user is moving it, not an animation.
- Shared-element transitions become an instant swap.
Gestures
Drawer, ActionSheet and the mobile Sidebar sheet share one contract.
| Contract | What it means |
|---|---|
| 1:1 tracking | While a finger drags the sheet, neither the panel nor the scrim has a transition. Both follow the finger frame for frame. |
| Velocity-scaled exit | A released swipe exits over 350ms scaled by the swipe's strength (35–350ms), so a hard flick lands fast. A swipe-dismissed scrim clears in 150ms. |
| One curve | Enter and exit, panel and scrim, all run ease-gesture, so the dim moves with the sheet. The enter takes 450ms. |
Shared elements
A list item and the view it opens can share a name and morph into each other through the browser's View Transitions. See Card → Shared-element transition.
Hide on scroll
BottomNav can slide away while the content scrolls down and return when it scrolls up. See BottomNav → Hide on scroll.
Momentum and overscroll
- Momentum belongs to the platform. Scrolling is native, touch and trackpad
inertia included, and no component re-implements it. Carousel's
variant="scroll"defaults todragFree, so a flick coasts instead of snapping to a slide. - Scroll bodies in popups and sheets contain their overscroll
(
overscroll-behavior: contain). A flick past the end of a menu, a list or a sheet body never scrolls the page behind it. - The page keeps its own overscroll. No component turns off the page's
rubber-band or pull-to-refresh. While an overlay holds a scroll lock,
<html>takesoverscroll-behavior: none, and it gets its own value back when the lock releases.