Flutter docs
Default skin

Motion contract

Animation is on by default here, which is why the timings are tokens: a component reads --cb-duration-base or asks the provider for a spring, and never writes its own numbers. Without that rule twenty components drift into five different rhythms.

Tokens

TokenValueUsed for
--cb-duration-instant80msState that must feel immediate: press, focus ring
--cb-duration-fast140msHover, colour changes
--cb-duration-base220msEnter and exit of overlays
--cb-duration-slow380msLarger movement, drawers
--cb-duration-deliberate620msThings meant to be watched: a ring filling

Springs are named too — snappy for controls, soft for surfaces, bouncy for celebratory moments.

MotionProvider

The provider wraps an application, so it is written out rather than staged. The footer under every example on this site reports what it currently resolves to.

tsx
import { MotionProvider, useMotionSettings } from '@ceebee/ui/client';
<MotionProvider scale={0.5}>       {/* everything at half speed */}  <App /></MotionProvider>
function Card() {  const { enabled, duration, spring } = useMotionSettings();  return <motion.div animate={{ opacity: 1 }} transition={spring('soft')} />;}
PropTypeDefaultNotes
enabledbooleantrueApp-level off switch — a settings toggle, or a test.
scalenumber1Multiplier on every duration. 0 is equivalent to disabled.

Reduced motion

prefers-reduced-motion: reduce is treated as a requirement, not a hint. It resolves enabled to false, collapses every duration to zero, and switches CSS animations off through --cb-motion-scale.

Do

Drop transforms and keep opacity, so the state change is still visible without movement.

Don't

Remove the feedback entirely — a dialog that appears with no transition at all is worse than one that fades.

Every animated component also takes motion={false} for a single opt-out that does not touch the provider.

Reveal and Stagger

Two primitives for content that arrives rather than pops. Both collapse to a plain fade under reduced motion — the transform is what goes, not the feedback.

Reveal animates one element on mount or on scroll into view. Stagger wraps each child in a Reveal with an increasing delay, so a list assembles instead of appearing all at once. Reload the page to watch them run again.

Arrived from below

Kebayoran Baru

Menteng

Senopati

Cipete

PropTypeDefaultNotes
from'below' | 'above' | 'left' | 'right' | 'none''below'Direction travelled from. Ignored under reduced motion.
distancenumber12Travel in px. Keep it small — large entrances read as sluggish.
delaynumber0Seconds before it starts.
spring'snappy' | 'soft' | 'bouncy''soft'Spring preset from the motion tokens.
onViewbooleanfalseWaits until it scrolls into view, and fires once.
stepnumber0.06Stagger only: seconds between children.