Gesso
Foundations

Motion

Behavior, not brand. Fade poppers. Scale centered dialogs. Translate sheets.

Motion is a system concern. Looks do not retune it. Durations live on primitives: --duration-fast is 120ms (control marks), --duration-base is 200ms (everything else). Easing is --ease-out (cubic-bezier(0.16, 1, 0.3, 1)).

Utilities: animate-fade-in / out, animate-pop-in / out, animate-check-in. Pop animates scale, not transform, so it does not stack on a centering translate. Always pair with motion-reduce:animate-none.

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

Overlay rules

Never animate transform on a popper or a centered overlay. Radix poppers already position with transform. Dialogs center with -translate-x-1/2 -translate-y-1/2. Fighting those makes the panel jump.

OverlayMotionWhy
Dropdown, select, tooltip, popoverFade onlyPopper transform stays intact
Dialog, alert-dialogFade overlay + pop contentPop uses scale
SheetFade overlay + slideSlide uses translate tokens
Accordion, collapsibleHeight keyframesToken accordion / collapsible
Checkbox markanimate-check-inFast duration
className={cn(
  "data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
  "motion-reduce:animate-none",
)}

Sheets use animate-slide-in-right (and left / top / bottom). Accordion and collapsible use animate-accordion-* / animate-collapsible-*. Do not reach for tw-animate-css. Keyframes are dry-* in bindings.css.

See Tokens for the token ladder. Dialog, sheet, and menu docs show the overlay pattern in situ.

On this page