Analyze a feature and add motion that improves clarity, feedback, perceived performance, and polish without making the interface feel slow, noisy, or theatrical.
MANDATORY PREPARATION
Users start this workflow with /animate. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the Context Gathering Protocol. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first. Additionally gather: performance constraints.
Consult the motion reference for timing, easing, choreography, and reduced-motion handling.
Consult the animate reference index when you need to browse the deeper motion library by use case instead of guessing filenames.
Consult the elevation system when motion should reinforce raised, pressed, inset, dragged, or layered depth.
Consult the interaction reference when animation decisions overlap with focus, loading, transitions, or feedback states.
Consult the component anatomy reference when motion affects custom primitives such as buttons, tabs, tooltips, toasts, toggles, drawers, or submit actions.
Consult the responsive design reference when motion needs to adapt across small screens, touch contexts, or reduced viewport space.
Consult the framework official docs reference before making framework-specific animation decisions.
Consult the React shadcn accelerators reference when the request overlaps with React toasts, drawers, text motion, or other UI patterns that already have strong accelerators.
Consult the CSS, Tailwind, and WAAPI motion reference to decide when modern CSS, Tailwind, or WAAPI can solve the motion cleanly without reaching for a framework animation library.
Consult the scroll-driven animations reference when motion should progress with scroll position rather than time.
Consult the view transitions reference when animating between page states or DOM changes with shared-element continuity.
Consult attribution and sources for the source lineage behind this skill's Emil-inspired motion guidance.
Consult entrance animations, exit animations, gesture interactions, and micro-interactions for consolidated thematic guidance by motion type.
Consult ease-out defaults, easing by context, and custom easing curves when choosing motion curves.
Consult UI under 300ms, asymmetric press and release timing, 500ms drawer timing, faster perceived performance, and tooltip timing escalation when the main question is duration rather than easing.
Consult on-screen movement easing, sheet and drawer easing, and spring motion when the motion pattern needs more specific guidance.
Consult damped drag boundaries, upward drag friction, interruptible animations, momentum dismissal, pointer capture, scroll and drag conflicts, and velocity-aware snap points when implementing gesture-heavy surfaces.
Consult blur-bridged transitions, clip-path tabs, respect reduced motion, opacity fallback, reduced motion alternatives, Motion's useReducedMotion, hover gap fill, scroll reveal thresholds, child orchestration, and toast stack depth for polish and accessibility refinement.
Consult transform and opacity only, avoid CSS variables in drag loops, clip-path reveals, hardware-accelerated motion under load, and surgical will-change for performance-sensitive property choices.
Consult immediate action feedback, interaction frequency, no keyboard animation, marketing exceptions, and animation purpose for strategy-heavy motion decisions.
Consult preserve-3d effects, never scale from zero, origin-aware animations, and percentage translateY when the question is really about transform technique and spatial feel.
Consult button press scale 0.97, scale affecting children, and SVG path morph disclosure icons for finer transform polish details.
If the interface already feels laggy under frequent use, also load optimize.
If the interface needs stronger resilience around reduced motion, errors, overflow, edge cases, or mixed input modes, also load harden.
Attribution and Inspiration
This skill's motion guidance is informed in part by Emil Kowalski's animations.dev course, especially the emphasis on easing choice, timing, tasteful restraint, springs, and motion that "feels right" in production UI.
It is also informed by Emil's animation-heavy open-source work on Sonner and Vaul, which are already relevant elsewhere in this library for React toast and drawer guidance.
This repository rewrites those lessons into original, repository-specific guidance rather than reproducing the course materials directly.
Motion Operating Model
Use this decision order before adding any animation:
- Fix structure first — motion should reinforce hierarchy and state, not rescue a confusing layout.
- Animate only with a job to do — every animation should improve feedback, orientation, relationship, or delight.
- Bias toward speed — product UI should feel responsive first and impressive second.
- Keep motion interruptible — new user intent beats finishing the old animation.
- Match the input method — mouse, touch, and keyboard interactions do not all deserve the same motion treatment.
- Plan reduced motion up front — accessibility is part of the system, not a cleanup pass.
- Prefer the lightest implementation that fits — modern CSS and Tailwind first, WAAPI when imperative timing matters, Motion when the interaction genuinely needs it.
Use motion for one or more of these jobs:
- Feedback — acknowledge that an action happened
- Orientation — help users understand where something came from or where it went
- Relationship — show how surfaces, layers, and controls relate spatially
- Delight — add warmth or personality after the fundamentals already work
If the animation cannot justify itself with one of those jobs, cut it.
Assess Motion Opportunities
Analyze where motion would improve the experience:
Identify static areas:
- Missing feedback: Actions without visual acknowledgment (button clicks, form submission, etc.)
- Jarring transitions: Instant state changes that feel abrupt (show/hide, page loads, route changes)
- Unclear relationships: Spatial or hierarchical relationships that aren't obvious
- Lack of delight: Functional but joyless interactions
- Missed guidance: Opportunities to direct attention or explain behavior
Understand the context:
- What's the personality? (Playful vs serious, energetic vs calm)
- What's the performance budget? (Compact-layout-first? Complex page?)
- Who's the audience? (Motion-sensitive users? Power users who want speed?)
- What matters most? (One hero animation vs many micro-interactions?)
- Which inputs matter? (mouse, touch, keyboard, stylus)
- Which interactions are high-frequency and should stay especially snappy?
If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
CRITICAL: Respect prefers-reduced-motion. Always provide non-animated alternatives for users who need them.
Motion should reinforce hierarchy, not compensate for weak hierarchy. If the layout only becomes understandable once it moves, fix the layout first.
Plan Animation Strategy
Create a purposeful animation plan:
- Hero moment: What's the ONE signature animation? (Page load? Hero section? Key interaction?)
- Feedback layer: Which interactions need acknowledgment?
- Transition layer: Which state changes need smoothing?
- Gesture layer: Which drag, swipe, snap, or dismiss interactions need physical logic?
- Delight layer: Where can we surprise and delight?
- Depth logic: Which elements should feel raised, pressed, dragged, inset, or layered?
- Reduced-motion plan: What simplifies to fade, blur, or instant state change?
- Performance budget: Which motions must stay lightweight because they happen often?
IMPORTANT: One well-orchestrated experience beats scattered animations everywhere. Focus on high-impact moments.
Default Motion Rules
Use these as the default guidelines for animation work unless the product context gives a strong reason to deviate.
1. Strategy and Purpose
- Every animation must earn its place through feedback, orientation, relationship, or delight.
- Product interfaces should usually feel fast, calm, and precise. Save slower or more dramatic motion for onboarding, hero moments, storytelling, or marketing surfaces.
- Favor one signature moment plus disciplined micro-interactions over adding motion everywhere.
- Do not animate keyboard-initiated actions just because pointer interactions animate. Keyboard users usually want predictable state change with minimal delay.
- The more often an interaction happens, the less motion it usually needs. High-frequency controls should feel nearly instant.
- Acknowledge user input immediately. Aim for visible feedback within roughly 80ms for micro-interactions whenever possible.
- If real work may exceed roughly 400ms, respond immediately with optimistic UI, skeletons, progress, or clear loading feedback instead of leaving a dead pause.
- Never use motion to disguise slow loading, weak hierarchy, or missing state design.
2. Easing Defaults
- Use ease-out as the default for entrances, reveals, and most feedback transitions.
- Use custom cubic-bezier curves instead of the generic CSS
ease default.
- Use ease-in-out for reversible, on-screen state changes that travel there and back.
- Use spring motion when the movement should feel physically connected to gesture input or object behavior.
- For drawers, sheets, and similar surfaces, a good starting point is the sheet-style curve
cubic-bezier(0.32, 0.72, 0, 1).
- Prefer exponential-style deceleration such as
ease-out-quart, ease-out-quint, or ease-out-expo for refined UI motion.
- Avoid bounce and elastic curves unless the product intentionally embraces a toy-like or playful physical metaphor. They usually feel dated, noisy, or self-conscious.
- Match easing to context:
- entering surfaces → ease-out
- exiting surfaces → shorter duration, often ease-in or a snappier exit curve
- state toggles / reversible movement → ease-in-out
- gesture-linked movement → spring or velocity-aware interpolation
3. Timing and Duration
- Keep most recurring UI motion under 300ms.
- Use 100-150ms for press states, toggles, color changes, and immediate acknowledgment.
- Use 200-300ms for standard UI state changes such as hover, menus, tooltips, and small reveals.
- Use 300-500ms for larger layout transitions such as drawers, modals, accordions, and major surface changes.
- Treat 500ms as a special-case upper bound for bigger surface motion like sheets or staged entrances, not as the default for ordinary controls.
- Exit animations should be faster than entrances. A good default is roughly 75% of enter duration.
- Press should be faster than release. Downward feedback should feel immediate; reset can be slightly softer.
- Delay the first tooltip or hover-revealed helper when needed, but make subsequent related reveals much faster or instant so the interface does not feel sticky.
- Long stagger chains are a smell. Cap total stagger time so the last item does not arrive embarrassingly late.
4. Property Selection and Performance
- Prefer animating transform and opacity.
- Avoid animating width, height, top, left, padding, margin, border-width, or other layout-heavy properties unless there is a strong reason and the surface is small.
- For accordion-like height transitions, prefer grid-template-rows or equivalent layout-friendly patterns over raw
height animation when possible.
- Use clip-path, masks, or composited reveals when you need a layout-free reveal effect.
- Use hardware-friendly transforms when the main thread is busy or the component animates frequently.
- Use
will-change sparingly and only when animation is imminent or proven to need it.
- During drag loops, avoid animation setups that route every frame through expensive CSS-variable or layout recalculation paths if they introduce lag.
- Prefer Intersection Observer for scroll-triggered motion and stop observing once the motion has completed if it only needs to happen once.
5. Transform and Scale Techniques
- For button or chip press feedback,
scale(0.97) is a strong default starting point.
- Never animate entry from
scale(0). Start closer to scale(0.95) or higher so the element keeps believable mass.
- Use percentage-based translate values when movement should scale with the element or viewport size.
- Make motion origin-aware:
- menus and tooltips should emerge from the trigger edge
- drawers and sheets should move from their anchored side
- lifted cards should feel like they rise from their current plane
- Remember that scaling affects children. Text and icons can feel blurry or distorted if the scale range is too aggressive.
- Use 3D transforms only when they improve spatial understanding or delight meaningfully. Do not reach for
preserve-3d just because it looks flashy in isolation.
6. Gesture and Interaction Patterns
- Make interactive animations interruptible. Users should not have to wait for motion to finish before expressing new intent.
- For swipe-to-dismiss, sheet snapping, and similar gestures, use distance plus velocity, not distance alone.
- Add friction or damping near boundaries so drags resist instead of hard-stopping.
- Handle scroll-vs-drag conflicts intentionally. Nested surfaces should not feel like they are fighting over input.
- Use robust pointer handling such as pointer capture or equivalent gesture ownership when implementing drag interactions.
- Visually lift dragged items with depth cues such as shadow, slight scale, or elevated layering.
- When a surface can be dragged past its resting point, allow controlled resistance instead of making the gesture feel abruptly blocked.
- Snap points should feel velocity-aware and purposefully chosen, not like arbitrary invisible walls.
7. Accessibility and Polish
- Always respect
prefers-reduced-motion.
- Reduced motion should usually mean simplified motion, not zero feedback. Replace large spatial movement with opacity, blur, highlight, or shorter transitions where possible.
- Preserve functional cues such as focus states, progress, loading feedback, and success or error acknowledgment.
- Use blur carefully to bridge between visual states when a straight cut feels harsh.
- Use stagger intentionally for orchestration, not as decoration. Small lists can benefit; huge lists usually cannot.
- Scroll reveals should trigger before the user has fully passed the element, but not so early that the effect feels detached from scroll context.
- Fill hover gaps between triggers and floating surfaces so tooltips, menus, and popovers do not flicker closed during pointer travel.
- Toast stacks can use offset, scale, and opacity to imply depth without becoming chaotic.
- Respect motion sensitivity in compact and touch-capable contexts as much as in wide layouts. Gesture-led movement can be especially uncomfortable if overdone.
Implement Animations
Add motion systematically across these categories:
Entrance Animations
- Page load choreography: Stagger only where it improves comprehension; keep total orchestration tight
- Hero section: Give the primary story moment a distinct entrance if the product tone supports it
- Content reveals: Scroll-triggered animations using intersection observer
- Modal/drawer entry: Smooth slide + fade, backdrop fade, focus management
Micro-interactions
- Button feedback:
- Hover: Subtle scale, color shift, or shadow change only if it improves affordance
- Click / press: Quick scale down then up, pressed-in feel, or depth shift
- Loading: Spinner or pulse state
- Form interactions:
- Input focus: Border, background, or elevation transition that clarifies focus without being distracting
- Validation: Prefer clear color, icon, or text-state change before ornamental motion
- Toggle switches: Smooth slide + color transition
- Checkboxes/radio: Clear state change with tight timing
- Like/favorite: Small scale or icon motion only if it fits the product tone
State Transitions
- Show/hide: Fade + slide (not instant), appropriate timing (200-300ms)
- Expand/collapse: Layout-friendly open/close transitions with overflow handling, icon rotation if helpful
- Loading states: Skeleton screen fades, spinner animations, progress bars
- Success/error: Color transitions, icon animations, gentle scale pulse
- Enable/disable: Opacity transitions, cursor changes
Navigation & Flow
- Page transitions: Crossfade between routes, shared element transitions when they truly clarify continuity
- Tab switching: Slide indicator, content fade, clip-path, or other fast directional cues
- Carousel/slider: Smooth transforms, snap points, momentum, and interruptible input
- Scroll effects: Parallax layers, sticky headers with state changes, scroll progress indicators
Feedback & Guidance
- Hover hints: Tooltip fade-ins, cursor changes, element highlights
- Drag & drop: Lift effect (shadow + scale), drop zone highlights, smooth repositioning — dragging should feel like the item pops forward on the z-axis
- Copy/paste: Brief highlight flash on paste, "copied" confirmation
- Focus flow: Highlight path through form or workflow
Depth & Elevation Motion
- Raised elements should feel like they move toward the user
- Pressed elements should feel like they move inward or downward
- Use shadow and movement together to communicate state, not just style
- Match motion emphasis to the same hierarchy logic used for color and typography
Delight Moments
- Empty states: Subtle floating animations on illustrations
- Completed actions: Confetti, check mark flourish, success celebrations
- Easter eggs: Hidden interactions for discovery
- Contextual animation: Weather effects, time-of-day themes, seasonal touches
Technical Implementation
Use appropriate techniques for each animation:
Timing & Easing
Durations by purpose:
- 100-150ms: Instant feedback (button press, toggle)
- 200-300ms: State changes (hover, menu open)
- 300-500ms: Layout changes (accordion, modal, drawer)
- 500ms max by default: Large surface transitions that truly need it
Easing curves (use these, not CSS defaults):
/* Recommended - natural deceleration */
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); /* Smooth, refined */
--ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); /* Slightly snappier */
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); /* Confident, decisive */
--ease-in-out-standard: cubic-bezier(0.65, 0, 0.35, 1); /* Reversible movement */
--ease-sheet-standard: cubic-bezier(0.32, 0.72, 0, 1); /* Sheets / drawers */
/* AVOID - feel dated and tacky */
/* bounce: cubic-bezier(0.34, 1.56, 0.64, 1); */
/* elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6); */
Exit animations are faster than entrances. Use ~75% of enter duration.
CSS Animations
/* Prefer for simple, declarative animations */
- transitions for state changes
- @keyframes for complex sequences
- transform + opacity first (GPU-friendly)
- Tailwind utilities when the project already uses Tailwind
JavaScript Animation
/* Use for complex, interactive animations */
- Web Animations API for programmatic control
- Framer Motion / Motion for React
- GSAP for complex sequences
Default rule: if a hover, press, reveal, or reduced-motion fallback can be expressed cleanly with modern CSS or Tailwind utilities, prefer that path before escalating to Motion.
Performance
- GPU acceleration: Use
transform and opacity, avoid layout properties
- will-change: Add sparingly for known expensive animations
- Reduce paint: Minimize repaints, use
contain where appropriate
- Monitor FPS: Ensure 60fps on target devices
- Interaction-first: Frequent product interactions should feel responsive even on weaker devices
Accessibility
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Prefer replacing large movement with short fades, highlights, blur transitions, or instant state changes instead of deleting every form of feedback.
Useful Default Values
Use these as starting points, then tune for context:
| Value |
Good default use |
scale(0.97) |
Button and chip press feedback |
scale(0.95) |
Minimum believable enter scale |
200ms |
Standard UI transition |
300ms |
Soft cap for common UI motion |
500ms |
Large sheet / drawer transition upper bound |
cubic-bezier(0.32, 0.72, 0, 1) |
Drawer / bottom-sheet easing |
10-16px |
Toast-stack offset starting range |
~100px from viewport edge |
Scroll-reveal trigger starting point |
NEVER:
- Use bounce or elastic easing curves by default—they draw attention to the animation itself
- Animate layout properties such as width, height, top, or left when transform or opacity would do the job
- Use long durations for routine feedback—it feels laggy fast
- Animate without purpose—every animation needs a reason
- Ignore
prefers-reduced-motion—this is an accessibility violation
- Animate everything—animation fatigue makes interfaces feel exhausting
- Force users to wait for motion to finish before they can continue
- Use motion to paper over weak structure, unclear hierarchy, or slow data fetching
- Ship gesture logic that ignores momentum, damping, or scroll conflicts
Verify Quality
Test animations thoroughly:
- Smooth at 60fps: No jank on target devices
- Feels natural: Easing curves feel organic, not robotic
- Appropriate timing: Not too fast (jarring) or too slow (laggy)
- Immediate acknowledgment: Inputs get visible response quickly
- Interruptible where needed: New intent can override old motion
- Gesture quality: Drag, swipe, snap, and dismiss interactions feel physically coherent
- Reduced motion works: Animations disabled or simplified appropriately
- Doesn't block: Users can interact during/after animations
- Adds value: Makes interface clearer or more delightful
Remember: the best UI animation usually feels inevitable, not attention-seeking. Animate with purpose, tune for responsiveness, respect accessibility, and let motion support the product instead of starring in it.
1---2name: animate3description: Improve or implement purposeful motion systems, micro-interactions, gestures, and transition behavior for production-grade UI. Use when the user mentions animation, motion, transitions, micro-interactions, hover states, drawers, toasts, gestures, or making the UI feel more alive.4---5
6Analyze a feature and add motion that improves clarity, feedback, perceived performance, and polish without making the interface feel slow, noisy, or theatrical.
7
8## MANDATORY PREPARATION
9
10Users start this workflow with `/animate`. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first. Additionally gather: performance constraints.
11
12Consult the [motion reference](../frontend-design/reference/motion-design.md) for timing, easing, choreography, and reduced-motion handling.
13Consult the [animate reference index](reference/README.md) when you need to browse the deeper motion library by use case instead of guessing filenames.
14Consult the [elevation system](../frontend-design/reference/elevation-system.md) when motion should reinforce raised, pressed, inset, dragged, or layered depth.
15Consult the [interaction reference](../frontend-design/reference/interaction-design.md) when animation decisions overlap with focus, loading, transitions, or feedback states.
16Consult the [component anatomy reference](../frontend-design/reference/component-anatomy.md) when motion affects custom primitives such as buttons, tabs, tooltips, toasts, toggles, drawers, or submit actions.
17Consult the [responsive design reference](../frontend-design/reference/responsive-design.md) when motion needs to adapt across small screens, touch contexts, or reduced viewport space.
18Consult the [framework official docs reference](../frontend-design/reference/framework-official-docs.md) before making framework-specific animation decisions.
19Consult the [React shadcn accelerators reference](../frontend-design/reference/react-shadcn-accelerators.md) when the request overlaps with React toasts, drawers, text motion, or other UI patterns that already have strong accelerators.
20Consult the [CSS, Tailwind, and WAAPI motion reference](../frontend-design/reference/css-tailwind-and-waapi-motion.md) to decide when modern CSS, Tailwind, or WAAPI can solve the motion cleanly without reaching for a framework animation library.
21Consult the [scroll-driven animations reference](../frontend-design/reference/scroll-driven-animations.md) when motion should progress with scroll position rather than time.
22Consult the [view transitions reference](../frontend-design/reference/view-transitions.md) when animating between page states or DOM changes with shared-element continuity.
23Consult [attribution and sources](reference/attribution-and-sources.md) for the source lineage behind this skill's Emil-inspired motion guidance.
24Consult [entrance animations](reference/entrance-animations.md), [exit animations](reference/exit-animations.md), [gesture interactions](reference/gesture-interactions.md), and [micro-interactions](reference/micro-interactions.md) for consolidated thematic guidance by motion type.
25Consult [ease-out defaults](reference/ease-out-default.md), [easing by context](reference/easing-context.md), and [custom easing curves](reference/custom-easing-curves.md) when choosing motion curves.
26Consult [UI under 300ms](reference/ui-under-300ms.md), [asymmetric press and release timing](reference/asymmetric-press-release.md), [500ms drawer timing](reference/drawer-500ms-duration.md), [faster perceived performance](reference/faster-improves-performance.md), and [tooltip timing escalation](reference/tooltip-delay-instant-followups.md) when the main question is duration rather than easing.
27Consult [on-screen movement easing](reference/ease-in-out-on-screen-movement.md), [sheet and drawer easing](reference/sheet-drawer-easing.md), and [spring motion](reference/spring-motion.md) when the motion pattern needs more specific guidance.
28Consult [damped drag boundaries](reference/damp-drag-boundaries.md), [upward drag friction](reference/upward-drag-friction.md), [interruptible animations](reference/interruptible-animations.md), [momentum dismissal](reference/momentum-dismissal.md), [pointer capture](reference/pointer-capture.md), [scroll and drag conflicts](reference/scroll-drag-conflicts.md), and [velocity-aware snap points](reference/velocity-aware-snap-points.md) when implementing gesture-heavy surfaces.
29Consult [blur-bridged transitions](reference/blur-bridge-states.md), [clip-path tabs](reference/clip-path-tab-transitions.md), [respect reduced motion](reference/respect-reduced-motion.md), [opacity fallback](reference/opacity-reduced-motion-fallback.md), [reduced motion alternatives](reference/reduced-motion-not-zero.md), [Motion's `useReducedMotion`](reference/use-reduced-motion-hook.md), [hover gap fill](reference/hover-gap-fill.md), [scroll reveal thresholds](reference/scroll-animation-threshold.md), [child orchestration](reference/stagger-children-orchestration.md), and [toast stack depth](reference/toast-stack-depth.md) for polish and accessibility refinement.
30Consult [transform and opacity only](reference/transform-opacity-only.md), [avoid CSS variables in drag loops](reference/avoid-css-variables-drag.md), [clip-path reveals](reference/clip-path-layout-free-reveals.md), [hardware-accelerated motion under load](reference/hardware-accelerated-busy-main-thread.md), and [surgical `will-change`](reference/will-change-subpixel-shift.md) for performance-sensitive property choices.
31Consult [immediate action feedback](reference/immediate-feedback-actions.md), [interaction frequency](reference/interaction-frequency.md), [no keyboard animation](reference/no-animation-for-keyboard.md), [marketing exceptions](reference/marketing-exception.md), and [animation purpose](reference/animation-purpose.md) for strategy-heavy motion decisions.
32Consult [preserve-3d effects](reference/preserve-3d-effects.md), [never scale from zero](reference/never-scale-zero.md), [origin-aware animations](reference/origin-aware-animations.md), and [percentage translateY](reference/percentage-translate-y.md) when the question is really about transform technique and spatial feel.
33Consult [button press scale 0.97](reference/button-press-scale-097.md), [scale affecting children](reference/scale-affects-children.md), and [SVG path morph disclosure icons](reference/svg-path-morph-disclosure.md) for finer transform polish details.
34
35If the interface already feels laggy under frequent use, also load `optimize`.
36If the interface needs stronger resilience around reduced motion, errors, overflow, edge cases, or mixed input modes, also load `harden`.
37
38---
39
40## Attribution and Inspiration
41
42This skill's motion guidance is informed in part by [Emil Kowalski's animations.dev course](https://animations.dev/), especially the emphasis on easing choice, timing, tasteful restraint, springs, and motion that "feels right" in production UI.
43
44It is also informed by Emil's animation-heavy open-source work on [Sonner](https://github.com/emilkowalski/sonner) and [Vaul](https://github.com/emilkowalski/vaul), which are already relevant elsewhere in this library for React toast and drawer guidance.
45
46This repository rewrites those lessons into original, repository-specific guidance rather than reproducing the course materials directly.
47
48---
49
50## Motion Operating Model
51
52Use this decision order before adding any animation:
53
541. **Fix structure first** — motion should reinforce hierarchy and state, not rescue a confusing layout.
552. **Animate only with a job to do** — every animation should improve feedback, orientation, relationship, or delight.
563. **Bias toward speed** — product UI should feel responsive first and impressive second.
574. **Keep motion interruptible** — new user intent beats finishing the old animation.
585. **Match the input method** — mouse, touch, and keyboard interactions do not all deserve the same motion treatment.
596. **Plan reduced motion up front** — accessibility is part of the system, not a cleanup pass.
607. **Prefer the lightest implementation that fits** — modern CSS and Tailwind first, WAAPI when imperative timing matters, Motion when the interaction genuinely needs it.
61
62Use motion for one or more of these jobs:
63
64- **Feedback** — acknowledge that an action happened
65- **Orientation** — help users understand where something came from or where it went
66- **Relationship** — show how surfaces, layers, and controls relate spatially
67- **Delight** — add warmth or personality after the fundamentals already work
68
69If the animation cannot justify itself with one of those jobs, cut it.
70
71## Assess Motion Opportunities
72
73Analyze where motion would improve the experience:
74
751. **Identify static areas**:
76 - **Missing feedback**: Actions without visual acknowledgment (button clicks, form submission, etc.)
77 - **Jarring transitions**: Instant state changes that feel abrupt (show/hide, page loads, route changes)
78 - **Unclear relationships**: Spatial or hierarchical relationships that aren't obvious
79 - **Lack of delight**: Functional but joyless interactions
80 - **Missed guidance**: Opportunities to direct attention or explain behavior
81
822. **Understand the context**:
83 - What's the personality? (Playful vs serious, energetic vs calm)
84 - What's the performance budget? (Compact-layout-first? Complex page?)
85 - Who's the audience? (Motion-sensitive users? Power users who want speed?)
86 - What matters most? (One hero animation vs many micro-interactions?)
87 - Which inputs matter? (mouse, touch, keyboard, stylus)
88 - Which interactions are high-frequency and should stay especially snappy?
89
90If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
91
92**CRITICAL**: Respect `prefers-reduced-motion`. Always provide non-animated alternatives for users who need them.
93
94Motion should reinforce hierarchy, not compensate for weak hierarchy. If the layout only becomes understandable once it moves, fix the layout first.
95
96## Plan Animation Strategy
97
98Create a purposeful animation plan:
99
100- **Hero moment**: What's the ONE signature animation? (Page load? Hero section? Key interaction?)
101- **Feedback layer**: Which interactions need acknowledgment?
102- **Transition layer**: Which state changes need smoothing?
103- **Gesture layer**: Which drag, swipe, snap, or dismiss interactions need physical logic?
104- **Delight layer**: Where can we surprise and delight?
105- **Depth logic**: Which elements should feel raised, pressed, dragged, inset, or layered?
106- **Reduced-motion plan**: What simplifies to fade, blur, or instant state change?
107- **Performance budget**: Which motions must stay lightweight because they happen often?
108
109**IMPORTANT**: One well-orchestrated experience beats scattered animations everywhere. Focus on high-impact moments.
110
111## Default Motion Rules
112
113Use these as the default guidelines for animation work unless the product context gives a strong reason to deviate.
114
115### 1. Strategy and Purpose
116
117- Every animation must earn its place through **feedback, orientation, relationship, or delight**.
118- Product interfaces should usually feel **fast, calm, and precise**. Save slower or more dramatic motion for onboarding, hero moments, storytelling, or marketing surfaces.
119- Favor **one signature moment plus disciplined micro-interactions** over adding motion everywhere.
120- Do **not** animate keyboard-initiated actions just because pointer interactions animate. Keyboard users usually want predictable state change with minimal delay.
121- The more often an interaction happens, the less motion it usually needs. High-frequency controls should feel nearly instant.
122- Acknowledge user input immediately. Aim for visible feedback within roughly **80ms** for micro-interactions whenever possible.
123- If real work may exceed roughly **400ms**, respond immediately with optimistic UI, skeletons, progress, or clear loading feedback instead of leaving a dead pause.
124- Never use motion to disguise slow loading, weak hierarchy, or missing state design.
125
126### 2. Easing Defaults
127
128- Use **ease-out** as the default for entrances, reveals, and most feedback transitions.
129- Use **custom cubic-bezier curves** instead of the generic CSS `ease` default.
130- Use **ease-in-out** for reversible, on-screen state changes that travel there and back.
131- Use **spring motion** when the movement should feel physically connected to gesture input or object behavior.
132- For drawers, sheets, and similar surfaces, a good starting point is the sheet-style curve `cubic-bezier(0.32, 0.72, 0, 1)`.
133- Prefer exponential-style deceleration such as `ease-out-quart`, `ease-out-quint`, or `ease-out-expo` for refined UI motion.
134- Avoid bounce and elastic curves unless the product intentionally embraces a toy-like or playful physical metaphor. They usually feel dated, noisy, or self-conscious.
135- Match easing to context:
136 - **entering surfaces** → ease-out
137 - **exiting surfaces** → shorter duration, often ease-in or a snappier exit curve
138 - **state toggles / reversible movement** → ease-in-out
139 - **gesture-linked movement** → spring or velocity-aware interpolation
140
141### 3. Timing and Duration
142
143- Keep most recurring UI motion under **300ms**.
144- Use **100-150ms** for press states, toggles, color changes, and immediate acknowledgment.
145- Use **200-300ms** for standard UI state changes such as hover, menus, tooltips, and small reveals.
146- Use **300-500ms** for larger layout transitions such as drawers, modals, accordions, and major surface changes.
147- Treat **500ms** as a special-case upper bound for bigger surface motion like sheets or staged entrances, not as the default for ordinary controls.
148- Exit animations should be faster than entrances. A good default is roughly **75%** of enter duration.
149- Press should be faster than release. Downward feedback should feel immediate; reset can be slightly softer.
150- Delay the **first** tooltip or hover-revealed helper when needed, but make subsequent related reveals much faster or instant so the interface does not feel sticky.
151- Long stagger chains are a smell. Cap total stagger time so the last item does not arrive embarrassingly late.
152
153### 4. Property Selection and Performance
154
155- Prefer animating **transform** and **opacity**.
156- Avoid animating **width, height, top, left, padding, margin, border-width**, or other layout-heavy properties unless there is a strong reason and the surface is small.
157- For accordion-like height transitions, prefer **grid-template-rows** or equivalent layout-friendly patterns over raw `height` animation when possible.
158- Use **clip-path**, masks, or composited reveals when you need a layout-free reveal effect.
159- Use hardware-friendly transforms when the main thread is busy or the component animates frequently.
160- Use `will-change` sparingly and only when animation is imminent or proven to need it.
161- During drag loops, avoid animation setups that route every frame through expensive CSS-variable or layout recalculation paths if they introduce lag.
162- Prefer Intersection Observer for scroll-triggered motion and stop observing once the motion has completed if it only needs to happen once.
163
164### 5. Transform and Scale Techniques
165
166- For button or chip press feedback, `scale(0.97)` is a strong default starting point.
167- Never animate entry from `scale(0)`. Start closer to `scale(0.95)` or higher so the element keeps believable mass.
168- Use percentage-based translate values when movement should scale with the element or viewport size.
169- Make motion **origin-aware**:
170 - menus and tooltips should emerge from the trigger edge
171 - drawers and sheets should move from their anchored side
172 - lifted cards should feel like they rise from their current plane
173- Remember that scaling affects children. Text and icons can feel blurry or distorted if the scale range is too aggressive.
174- Use 3D transforms only when they improve spatial understanding or delight meaningfully. Do not reach for `preserve-3d` just because it looks flashy in isolation.
175
176### 6. Gesture and Interaction Patterns
177
178- Make interactive animations **interruptible**. Users should not have to wait for motion to finish before expressing new intent.
179- For swipe-to-dismiss, sheet snapping, and similar gestures, use **distance plus velocity**, not distance alone.
180- Add **friction or damping** near boundaries so drags resist instead of hard-stopping.
181- Handle **scroll-vs-drag conflicts** intentionally. Nested surfaces should not feel like they are fighting over input.
182- Use robust pointer handling such as pointer capture or equivalent gesture ownership when implementing drag interactions.
183- Visually lift dragged items with depth cues such as shadow, slight scale, or elevated layering.
184- When a surface can be dragged past its resting point, allow controlled resistance instead of making the gesture feel abruptly blocked.
185- Snap points should feel velocity-aware and purposefully chosen, not like arbitrary invisible walls.
186
187### 7. Accessibility and Polish
188
189- Always respect `prefers-reduced-motion`.
190- Reduced motion should usually mean **simplified motion**, not zero feedback. Replace large spatial movement with opacity, blur, highlight, or shorter transitions where possible.
191- Preserve functional cues such as focus states, progress, loading feedback, and success or error acknowledgment.
192- Use blur carefully to bridge between visual states when a straight cut feels harsh.
193- Use stagger intentionally for orchestration, not as decoration. Small lists can benefit; huge lists usually cannot.
194- Scroll reveals should trigger before the user has fully passed the element, but not so early that the effect feels detached from scroll context.
195- Fill hover gaps between triggers and floating surfaces so tooltips, menus, and popovers do not flicker closed during pointer travel.
196- Toast stacks can use offset, scale, and opacity to imply depth without becoming chaotic.
197- Respect motion sensitivity in compact and touch-capable contexts as much as in wide layouts. Gesture-led movement can be especially uncomfortable if overdone.
198
199## Implement Animations
200
201Add motion systematically across these categories:
202
203### Entrance Animations
204- **Page load choreography**: Stagger only where it improves comprehension; keep total orchestration tight
205- **Hero section**: Give the primary story moment a distinct entrance if the product tone supports it
206- **Content reveals**: Scroll-triggered animations using intersection observer
207- **Modal/drawer entry**: Smooth slide + fade, backdrop fade, focus management
208
209### Micro-interactions
210- **Button feedback**:
211 - Hover: Subtle scale, color shift, or shadow change only if it improves affordance
212 - Click / press: Quick scale down then up, pressed-in feel, or depth shift
213 - Loading: Spinner or pulse state
214- **Form interactions**:
215 - Input focus: Border, background, or elevation transition that clarifies focus without being distracting
216 - Validation: Prefer clear color, icon, or text-state change before ornamental motion
217- **Toggle switches**: Smooth slide + color transition
218- **Checkboxes/radio**: Clear state change with tight timing
219- **Like/favorite**: Small scale or icon motion only if it fits the product tone
220
221### State Transitions
222- **Show/hide**: Fade + slide (not instant), appropriate timing (200-300ms)
223- **Expand/collapse**: Layout-friendly open/close transitions with overflow handling, icon rotation if helpful
224- **Loading states**: Skeleton screen fades, spinner animations, progress bars
225- **Success/error**: Color transitions, icon animations, gentle scale pulse
226- **Enable/disable**: Opacity transitions, cursor changes
227
228### Navigation & Flow
229- **Page transitions**: Crossfade between routes, shared element transitions when they truly clarify continuity
230- **Tab switching**: Slide indicator, content fade, clip-path, or other fast directional cues
231- **Carousel/slider**: Smooth transforms, snap points, momentum, and interruptible input
232- **Scroll effects**: Parallax layers, sticky headers with state changes, scroll progress indicators
233
234### Feedback & Guidance
235- **Hover hints**: Tooltip fade-ins, cursor changes, element highlights
236- **Drag & drop**: Lift effect (shadow + scale), drop zone highlights, smooth repositioning — dragging should feel like the item pops forward on the z-axis
237- **Copy/paste**: Brief highlight flash on paste, "copied" confirmation
238- **Focus flow**: Highlight path through form or workflow
239
240### Depth & Elevation Motion
241- Raised elements should feel like they move toward the user
242- Pressed elements should feel like they move inward or downward
243- Use shadow and movement together to communicate state, not just style
244- Match motion emphasis to the same hierarchy logic used for color and typography
245
246### Delight Moments
247- **Empty states**: Subtle floating animations on illustrations
248- **Completed actions**: Confetti, check mark flourish, success celebrations
249- **Easter eggs**: Hidden interactions for discovery
250- **Contextual animation**: Weather effects, time-of-day themes, seasonal touches
251
252## Technical Implementation
253
254Use appropriate techniques for each animation:
255
256### Timing & Easing
257
258**Durations by purpose:**
259- **100-150ms**: Instant feedback (button press, toggle)
260- **200-300ms**: State changes (hover, menu open)
261- **300-500ms**: Layout changes (accordion, modal, drawer)
262- **500ms max by default**: Large surface transitions that truly need it
263
264**Easing curves (use these, not CSS defaults):**
265```css
266/* Recommended - natural deceleration */
267--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); /* Smooth, refined */
268--ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); /* Slightly snappier */
269--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); /* Confident, decisive */
270--ease-in-out-standard: cubic-bezier(0.65, 0, 0.35, 1); /* Reversible movement */
271--ease-sheet-standard: cubic-bezier(0.32, 0.72, 0, 1); /* Sheets / drawers */
272
273/* AVOID - feel dated and tacky */
274/* bounce: cubic-bezier(0.34, 1.56, 0.64, 1); */
275/* elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6); */
276```
277
278**Exit animations are faster than entrances.** Use ~75% of enter duration.
279
280### CSS Animations
281```css
282/* Prefer for simple, declarative animations */
283- transitions for state changes
284- @keyframes for complex sequences
285- transform + opacity first (GPU-friendly)
286- Tailwind utilities when the project already uses Tailwind
287```
288
289### JavaScript Animation
290```javascript
291/* Use for complex, interactive animations */
292- Web Animations API for programmatic control
293- Framer Motion / Motion for React
294- GSAP for complex sequences
295```
296
297Default rule: if a hover, press, reveal, or reduced-motion fallback can be expressed cleanly with modern CSS or Tailwind utilities, prefer that path before escalating to Motion.
298
299### Performance
300- **GPU acceleration**: Use `transform` and `opacity`, avoid layout properties
301- **will-change**: Add sparingly for known expensive animations
302- **Reduce paint**: Minimize repaints, use `contain` where appropriate
303- **Monitor FPS**: Ensure 60fps on target devices
304- **Interaction-first**: Frequent product interactions should feel responsive even on weaker devices
305
306### Accessibility
307```css
308@media (prefers-reduced-motion: reduce) {
309 * {
310 animation-duration: 0.01ms !important;
311 animation-iteration-count: 1 !important;
312 transition-duration: 0.01ms !important;
313 }
314}
315```
316
317Prefer replacing large movement with short fades, highlights, blur transitions, or instant state changes instead of deleting every form of feedback.
318
319## Useful Default Values
320
321Use these as starting points, then tune for context:
322
323| Value | Good default use |
324| --- | --- |
325| `scale(0.97)` | Button and chip press feedback |
326| `scale(0.95)` | Minimum believable enter scale |
327| `200ms` | Standard UI transition |
328| `300ms` | Soft cap for common UI motion |
329| `500ms` | Large sheet / drawer transition upper bound |
330| `cubic-bezier(0.32, 0.72, 0, 1)` | Drawer / bottom-sheet easing |
331| `10-16px` | Toast-stack offset starting range |
332| `~100px` from viewport edge | Scroll-reveal trigger starting point |
333
334**NEVER**:
335- Use bounce or elastic easing curves by default—they draw attention to the animation itself
336- Animate layout properties such as width, height, top, or left when transform or opacity would do the job
337- Use long durations for routine feedback—it feels laggy fast
338- Animate without purpose—every animation needs a reason
339- Ignore `prefers-reduced-motion`—this is an accessibility violation
340- Animate everything—animation fatigue makes interfaces feel exhausting
341- Force users to wait for motion to finish before they can continue
342- Use motion to paper over weak structure, unclear hierarchy, or slow data fetching
343- Ship gesture logic that ignores momentum, damping, or scroll conflicts
344
345## Verify Quality
346
347Test animations thoroughly:
348
349- **Smooth at 60fps**: No jank on target devices
350- **Feels natural**: Easing curves feel organic, not robotic
351- **Appropriate timing**: Not too fast (jarring) or too slow (laggy)
352- **Immediate acknowledgment**: Inputs get visible response quickly
353- **Interruptible where needed**: New intent can override old motion
354- **Gesture quality**: Drag, swipe, snap, and dismiss interactions feel physically coherent
355- **Reduced motion works**: Animations disabled or simplified appropriately
356- **Doesn't block**: Users can interact during/after animations
357- **Adds value**: Makes interface clearer or more delightful
358
359Remember: the best UI animation usually feels inevitable, not attention-seeking. Animate with purpose, tune for responsiveness, respect accessibility, and let motion support the product instead of starring in it.