Motion
Calm and purposeful. Respect prefers-reduced-motion. When in doubt, do less.
Timing, libraries & snippetShowHide
Durations
- instant
- 0ms — Reduced-motion fallback
- fast
- 200ms — Hovers, chips
- base
- 500ms — Section reveals
- expressive
- 700ms — Hero accents — sparingly
- theme
- 360ms — Color cross-fade (globals.css)
Libraries
- motion/react — Enter/exit, layout, in-view reveals
- GSAP + ScrollTrigger — Scroll scenes, brush paths
- Locomotive + Lenis — Smooth scroll on marketing pages
- CSS transitions — Theme, focus rings, simple hovers
const reduced = useReducedMotion();
<motion.section
initial={reduced ? { opacity: 1, y: 0 } : { opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-80px' }}
transition={reduced ? { duration: 0 } : { duration: 0.5, ease: 'easeOut' }}
/>Do & don’t
Interact with the left column. Motion should orient or confirm — never decorate.
Section revealOnce on enter — not a looping headline
Do
Featured work
Don't
Featured work
Card hoverSubtle scale; disabled when reduced motion
Do
Hover
Don't
Hover
Tap feedback
Do
Don't
LoadingSkeleton, not a fake progress bar
Do
Don't