Animation System

Motion Guide

Motion should be felt, not seen. All animation variants live in lib/motion.ts - never defined inline in components.

Philosophy

Purposeful

Every animation communicates state change, hierarchy, or direction.

Proportional

Short transitions for small elements, longer for full-page changes.

Respectful

All animations respect prefers-reduced-motion OS setting.

Easing Curves

gridnest-out

cubic-bezier(0.16, 1, 0.3, 1)

gridnest-spring

cubic-bezier(0.34, 1.56, 0.64, 1)

ease-in-out (default)

easeInOut

Timing Scale

Fast

150ms

Tap, hover, icon swaps

Normal

250ms

Menus, popovers, inline feedback

Slow

400ms

Page sections, larger layout reveals

Component Recipes

ComponentTriggerDurationGuidance
Buttonpress / hover150msUse tiny scale or y movement only.
Dropdownopen / close150-200msFade and scale from trigger origin.
Modalenter / exit250-300msPair backdrop fade with panel scale.
Listspage reveal400msUse staggerContainer with short child delay.

Variants Gallery

fadeUp

opacity + y translate reveal. Used on headlines and body text.

Animated element

scaleIn

scale + opacity entrance. Used on cards, modals, and preview panels.

Animated element

clipReveal

Horizontal clip-path text reveal. Used for editorial headlines.

Animated element

Do / Don't

Do

  • Import variants from lib/motion.ts
  • Use staggerContainer for list reveals
  • Respect useReducedMotion()
  • Keep durations under 500ms for UI

Don't

  • Define animation variants inline in components
  • Animate on every scroll event
  • Use durations > 700ms for UI feedback
  • Animate layout-triggering properties (width, height)