Skip to content

Motion System

Human’s motion system applies Pixar’s 12 principles of animation to UI interactions. Every animation has purpose — it guides attention, confirms actions, and creates spatial coherence.

| Token | Value | CSS Variable | Usage | | ------------------ | :---: | ----------------------- | --------------------------------- | | duration.instant | 100ms | --hu-duration-instant | Hovers, state toggles | | duration.fast | 150ms | --hu-duration-fast | Button presses, small reveals | | duration.normal | 250ms | --hu-duration-normal | Panel transitions, fades | | duration.slow | 400ms | --hu-duration-slow | Modal entrances, page transitions | | duration.slower | 600ms | --hu-duration-slower | Complex orchestrated sequences |

| Token | Value | CSS Variable | Character | | -------------- | ----------------------------------------- | ------------------- | --------------------- | | ease.default | cubic-bezier(0.4, 0, 0.2, 1) | --hu-ease-default | Natural deceleration | | ease.in | cubic-bezier(0.4, 0, 1, 1) | --hu-ease-in | Accelerating exit | | ease.out | cubic-bezier(0, 0, 0.2, 1) | --hu-ease-out | Decelerating entrance | | ease.in-out | cubic-bezier(0.4, 0, 0.2, 1) | --hu-ease-in-out | Symmetric motion | | ease.spring | cubic-bezier(0.175, 0.885, 0.32, 1.275) | --hu-ease-spring | Bouncy overshoot | | ease.bounce | cubic-bezier(0.34, 1.56, 0.64, 1) | --hu-ease-bounce | Playful bounce |

These presets encode Pixar animation principles as token-driven CSS keyframes.

When pressed, buttons compress slightly (squash), then spring back with overshoot (stretch).

| Token | Value | Principle | | --------------------------------------- | ------- | ---------------------- | | micro-physics.button-press.scale | 0.96 | Squash on press | | micro-physics.button-press.duration | 80ms | Fast physical response | | micro-physics.button-release.scale | 1.02 | Stretch on release | | micro-physics.button-release.duration | 200ms | Slower recovery |

.btn:active {
transform: scale(var(--hu-physics-button-press-scale));
transition: transform var(--hu-physics-button-press-duration)
var(--hu-ease-spring);
}

Before appearing, modals briefly scale down (anticipation), then spring to full size.

| Token | Value | Principle | | ------------------------------------------- | ------- | -------------------- | | micro-physics.modal-anticipation.scale | 0.95 | Preparatory pullback | | micro-physics.modal-anticipation.duration | 120ms | Brief setup |

Cards lift slightly with a springy overshoot on hover, settling to final position.

| Token | Value | Principle | | -------------------------------------- | ------- | ------------ | | micro-physics.card-hover.translate-y | -2px | Subtle lift | | micro-physics.card-hover.duration | 300ms | Gentle float |

Dropdowns compress before expanding, giving a sense of stored energy.

| Token | Value | Principle | | ---------------------------------------------- | ------- | -------------------- | | micro-physics.dropdown-anticipation.scale-y | 0.95 | Vertical compression | | micro-physics.dropdown-anticipation.duration | 100ms | Quick wind-up |

Toggle switches squash horizontally during state change.

| Token | Value | Principle | | -------------------------------------- | ------- | ----------------- | | micro-physics.toggle-squash.scale-x | 0.9 | Horizontal squash | | micro-physics.toggle-squash.duration | 150ms | Snappy |

Applies button press squash/stretch on any interactive element:

<button class="hu-physics-press">Click me</button>

Applies card hover lift with follow-through:

<div class="hu-physics-hover">Hoverable card</div>

Applies anticipation entrance animation on mount:

<dialog class="hu-anticipate-enter">Modal content</dialog>

All animations respect prefers-reduced-motion: reduce. When active:

  • Durations are set to 0ms
  • Transforms are removed
  • Only opacity transitions remain (they don’t cause motion sickness)
@media (prefers-reduced-motion: reduce) {
.hu-physics-press:active,
.hu-physics-hover:hover {
transform: none !important;
transition: none !important;
}
}

| Scenario | Duration | Easing | Principle | | ---------------- | --------- | ---------- | ---------------- | | Button feedback | instant | spring | Squash & stretch | | Card hover | normal | spring | Follow-through | | Modal entrance | slow | bounce | Anticipation | | Page transition | slow | ease-out | Staging | | Toast appearance | fast | ease-out | Timing | | Loading spinner | slower | linear | Secondary action |

  • Scrolling content into view (use CSS scroll-behavior: smooth instead)
  • Color theme transitions (instant swap, no fade)
  • Error state changes (immediate, no delay)
  • Content that hasn’t changed (don’t re-animate)