Gesso
Foundations

Motion

Choose a duration, an easing, and an animation utility for an overlay, a mark, or a panel.

Motion in the kit is behavior and no look retunes it. This page gives the two durations, the one easing, and the animation utilities, and then the rules for which animation an overlay uses, so a new popper, dialog, or panel moves like the ones around it.

Two durations cover everything. --duration-fast is 120ms and is used for control marks and for the fade of sidebar labels. --duration-base is 200ms and is used for everything else. The easing is --ease-out, which is cubic-bezier(0.16, 1, 0.3, 1).

Utilities

UtilityDoesDuration
animate-fade-in and animate-fade-outOpacitybase
animate-pop-in and animate-pop-outOpacity and scale from 0.96 to 1base
animate-check-inOpacity and scale from 0.5 to 1fast
animate-slide-in-right, -left, -top, and -bottom, with matching animate-slide-out-*translate from or to the edgebase
animate-accordion-down and -upHeight, from the Radix accordion content heightbase
animate-collapsible-down and -upHeight, from the Radix collapsible content heightbase

The fade-out, pop-out, and slide-out utilities hold their end state. Pop animates scale and the slides animate translate, so neither stacks on the transform that a popper or a centered dialog already uses. The keyframes are named dry-* in bindings.css, so do not add tw-animate-css.

animate-fade-in
animate-pop-in
animate-check-in

Overlay rules

Do not animate transform on a popper or a centered overlay. Radix poppers position themselves with transform, and dialogs center with -translate-x-1/2 -translate-y-1/2, so animating transform on top of those makes the panel jump.

OverlayMotionReason
Dropdown menu, context menu, select, tooltip, popover, hover cardFade onlyThe popper transform stays intact
Dialog and alert dialogFade the overlay and pop the contentPop uses scale
SheetFade the overlay and slide the contentSlide uses translate
Accordion and collapsibleHeight keyframesThey animate to the measured content height
Checkbox markanimate-check-inIt is a control mark, so it uses the fast duration
className={cn(
  "data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
  "motion-reduce:animate-none",
)}

Components that move on their own

  • Tabs moves its active line so that the leading edge travels first and the mark stretches, then the trailing edge catches up. The lead is --duration-fast and the trail is --duration-base, both on --ease-out.
  • Sidebar collapses to icons in CSS. The panel and each row tween their width on --duration-base and --ease-out.
  • WorkMark and PriorityBars use one spring (stiffness 420, damping 40, mass 0.9). Marks that change together stagger by 28ms, and a mark on first render appears without animating.
  • Interactive card lifts, zooms its media, or reveals its actions on hover and focus, on --duration-base and --ease-out. Reduced motion leaves the card still and keeps the actions visible.

Accessibility

  • The overlay components pair each animation utility with motion-reduce:animate-none, so a reader who prefers reduced motion gets overlays that appear without animating. Add the same class to any new use of these utilities.
  • The Tabs line, WorkMark, and PriorityBars check the reduced motion preference in code and jump to their end state, and the Sidebar width tween carries motion-reduce:transition-none.
  • Interactive card's lift, zoom, and reveal run only under motion-safe, so reduced motion leaves the card still and keeps its actions visible. The lift shadow still steps, with no transition.

Next

Elevation covers the shadows that the pop and slide overlays carry. Dialog, Sheet, and Popover show the overlay patterns in place.

On this page