From grimoire
Guides adding purposeful UI animations & micro-interactions with functional roles, performance constraints (100-500ms), and `prefers-reduced-motion` fallbacks for accessibility.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-motion-designThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Assign every animation a functional purpose, constrain duration to 100–500ms, use performant CSS properties only, and provide a reduced-motion fallback.
Assign every animation a functional purpose, constrain duration to 100–500ms, use performant CSS properties only, and provide a reduced-motion fallback.
Adopted by: Google Material Design (2022) defines a complete motion system with duration tokens, easing functions, and choreography guidelines — applied across all Google products; Apple HIG "Animation" specifies that animation must have meaning and purpose, not be decorative, with explicit guidance on when to omit animation; IBM Carbon Design System includes motion guidelines with duration scale and easing tokens; Val Head's "Designing Interface Animation" (Rosenfeld Media, 2016) is the primary industry reference for motion principles
Impact: Google Material Design team: purposeful motion reduces perceived wait time by 33% compared to abrupt state changes with identical actual latency; Issara Willenskomer documents that motion communicates spatial relationships, object persistence, and cause-effect chains that static UI cannot — users orient 40% faster in animated navigation transitions vs cut transitions (UX in Motion, 2017); Vestibular Disorders Association (2022) identifies uncontrolled website animation as a top-3 trigger for vestibular symptoms (dizziness, nausea) — estimated 35% of adults over 40 have experienced vestibular dysfunction, making prefers-reduced-motion a medical accessibility requirement, not a preference
Why best: Decorative animation (animation without a functional role) degrades performance, increases perceived cognitive load, and can cause harm — the alternative of no animation is better than animation without purpose; purposeful animation (communicating state change, spatial context, feedback) earns its performance cost
Sources: Google Material Design 3 "Motion" (m3.material.io, 2022); Apple HIG "Animation" (developer.apple.com, 2023); Val Head "Designing Interface Animation" (Rosenfeld Media, 2016); Willenskomer "12 Principles of UX in Motion" (Medium, 2017); Vestibular Disorders Association "Dizziness and Motion Sickness" (vestibular.org, 2022)
Every animation must serve at least one of four functional roles:
| Role | What it communicates | Example |
|---|---|---|
| Orient | Spatial relationship — where something came from or went to | Page slide transition (right → left = forward navigation) |
| Feedback | Confirmation that an action was received | Button press ripple, checkbox check animation |
| Direct attention | Draws eye to a new, important element | Notification badge pulse, new message highlight |
| Delight | Reward for completion — used sparingly | Success state confetti, onboarding celebration |
If an animation doesn't serve one of these roles, remove it. Decorative animation is not a valid use case.
Ask: "What does the user learn from this motion that they couldn't learn from a static state change?"
Duration is the most common motion design mistake. Animations that feel sluggish or jarring almost always have incorrect duration:
| Animation type | Duration range | Rationale |
|---|---|---|
| Micro-interactions (button press, checkbox, toggle) | 100–200ms | Faster than perception threshold for "snap" — feels immediate |
| Component transitions (dropdown open, modal appear, tooltip) | 200–300ms | Visible but not slow; matches natural eye movement speed |
| Page / view transitions | 300–500ms | Needs enough time to communicate spatial context |
| Complex choreography (multi-element staggered entrance) | 400–600ms per sequence | Each element 50–80ms staggered after the previous |
| Never | > 700ms for UI animations | Users perceive this as slow loading, not design |
Material Design's duration tokens:
--md-sys-motion-duration-short1: 50ms (exit/fade of small elements)
--md-sys-motion-duration-short2: 100ms
--md-sys-motion-duration-medium1: 200ms
--md-sys-motion-duration-medium2: 300ms
--md-sys-motion-duration-long1: 400ms (complex page transitions)
--md-sys-motion-duration-long2: 500ms
Easing determines whether motion feels natural or mechanical:
| Easing | CSS value | Use for |
|---|---|---|
| Ease-out (fast start, slow finish) | cubic-bezier(0.0, 0.0, 0.2, 1) | Entering elements — fast arrival feels intentional |
| Ease-in (slow start, fast finish) | cubic-bezier(0.4, 0.0, 1, 1) | Exiting elements — quick departure avoids dragging |
| Ease-in-out (slow-fast-slow) | cubic-bezier(0.4, 0.0, 0.2, 1) | Elements that move across the screen — natural arc |
| Linear | linear | Loops and spinners only — linear feels mechanical for one-shot transitions |
Material Design standard easing: cubic-bezier(0.2, 0, 0, 1) — used for most container transitions.
Never use ease (CSS default): CSS ease is cubic-bezier(0.25, 0.1, 0.25, 1) — a compromise that feels neither intentional nor natural. Use a specific easing token.
Properties that trigger layout or paint cause jank — the animation drops frames:
❌ Jank-causing properties (avoid animating):
width, height, margin, padding, top, left, right, bottom
font-size, border-width, box-shadow (partially)
✅ GPU-composited properties (safe to animate):
transform: translate(), scale(), rotate()
opacity
filter (modern browsers, with caveats)
Example:
❌ .panel { transition: height 300ms; } /* triggers layout */
✅ .panel { transition: transform 300ms; } /* GPU-composited */
.panel.open { transform: scaleY(1); }
.panel.closed { transform: scaleY(0); transform-origin: top; }
Use will-change: transform only when needed: will-change promotes an element to its own compositor layer — useful for complex animations, costly for static elements. Add it immediately before an animation starts (via JS), remove it after.
prefers-reduced-motion supportThis is a medical accessibility requirement, not a preference:
/* Base: full animation */
.modal {
transition: opacity 300ms ease-out, transform 300ms ease-out;
}
/* Reduced motion: instant state change */
@media (prefers-reduced-motion: reduce) {
.modal {
transition: none;
}
}
What to keep vs remove under reduced motion:
| Keep | Remove / replace |
|---|---|
| Instant state changes (show/hide) | All transitions and animations |
| Color changes (hover, active states) | Scroll-triggered animations |
| Static focus indicators | Parallax effects |
| Functional feedback (spinners) | Auto-playing motion |
Test: In macOS: System Settings → Accessibility → Display → Reduce Motion. In Windows: Settings → Ease of Access → Display → Show animations. Verify the experience is fully functional with all motion disabled.
When multiple elements animate together, choreography determines which animates first:
Entrance: hero content first → supporting content after
[Heading appears] → [Body text fades in 80ms later] → [CTA appears 80ms later]
Exit: reverse order — supporting content first, primary last
[CTA fades out] → [Body text fades 80ms later] → [Heading exits 80ms later]
Stagger delay: 50–80ms per element
Never animate all elements simultaneously at identical duration — it looks like a PowerPoint transition, not a designed animation.
Never stagger more than 5 elements — beyond 5, the sequence feels like a loading delay, not choreography.
Animations that run at 60fps on a MacBook Pro may drop to 20fps on a mid-range Android phone. Required testing:
Lighthouse animation audit: Lighthouse flags "Avoid non-composited animations" as a performance issue — use this as a CI gate.
easetransform and opacity in performance-critical animations — no width, height, margin, or paddingprefers-reduced-motion: reduce must disable all transitions and animations — instant state changes remainease on every transition — elements feel neither fast nor intentional; define explicit easing tokensheight from 0 to auto causes layout thrash and jank; use transform: scaleY() or max-height with overflow:hidden insteadnpx claudepluginhub jeffreytse/grimoire --plugin grimoireGuides purposeful UI motion choreography for animation sequences, page transitions, micro-interactions, and loading states, ensuring performance and reduced-motion accessibility.
Applies animation principles like easing, durations, stagger, and sequencing to UI motion for natural, performant interactions. Supports accessibility and low-power devices.
Applies Disney's 12 animation principles to UI motion: easing curves, duration guidelines, choreography, and reduced-motion accessibility. Use when designing state changes, transitions, or motion systems.