Skip to content

Motion

Shared timing, easing, distance, and stagger values for reusable cascade motion.

One entrance, three speeds. Choose the duration that matches the visual weight of the surface, then cascade elements in reading order.

| Utility | Duration | Use for | | ------------------------ | -------- | ---------------------------------------------- | | animate-cascade-in-fast | 160ms | Sidebar and nav-rail items | | animate-cascade-in | 200ms | Mid-weight chrome | | animate-cascade-in-slow | 280ms | Page headers, content frames, rows, and cards |

Each one fades in while rising the settle distance, on the shared ease-out curve, with animation-fill-mode: backwards so a delayed item waits its turn invisible rather than flashing first.

| Token | Value | CSS variable | | --------------- | ----------------------------- | -------------------------------- | | Ease out | cubic-bezier(0, 0, 0.58, 1) | --motion-cascade-ease | | Settle distance | 6px | --motion-cascade-distance | | Stagger | 40ms | --motion-cascade-stagger |

duration-cascade-fast, duration-cascade, duration-cascade-slow, and ease-cascade are also available as transition utilities, for state changes that are not entrances.

<div className="animate-cascade-in-slow motion-reduce:animate-none" style={{ animationDelay: '40ms' }} />

Reduced motion is handled twice over: the shared class constants carry motion-reduce:animate-none, and global.css disables animate-cascade-in* under prefers-reduced-motion: reduce for anyone using the utility directly.

stylus-ui/Motion ships the cascade as an API, not just as tokens. Reach for it rather than pairing a class with a delay by hand.

| Export | Use for | | --- | --- | | getCascadeMotionProps(index, { track }) | One step of a cascade, as a spreadable { className, style }. Returning both together is the point — a fast item cannot end up with a default item's delay. | | createCascadeSequence({ startIndex, track, enabled }) | A run of elements whose presence is conditional. next() takes the step where the element renders, so an item that does not render does not leave a gap. | | getCascadeCollectionMotionProps(index, { startIndex }) | Rows and cards. Clamps a long list into one short window, so a hundred items finish when five would. | | useEntranceMotion(surface) | Play the entrance on the first visit of a browser session and stay quiet on every return. | | getCascadeRowMotionProps() (from stylus-ui/DataTable) | A DataTable's rows — spread it straight onto the table. |