Agent skill

ui-animation

Guide tasteful UI animation with easing, springs, layout animations, gestures, and accessibility. Covers Tailwind and Motion patterns. Use when: (1) Implementing enter/exit animations, (2) Choosing easing curves, (3) Configuring springs, (4) Layout animations and shared elements, (5) Drag/swipe gestures, (6) Micro-interactions, (7) Ensuring prefers-reduced-motion accessibility. Triggers: animate, animation, easing, spring, transition, motion, layout, gesture, drag, swipe, reduced motion, framer motion.

Stars 2
Forks 0

Install this agent skill to your Project

npx add-skill https://github.com/LukasStrickler/ai-dev-atelier/tree/main/content/skills/ui-animation

Metadata

Additional technical details for this skill

author
ai-dev-atelier
version
1.0

SKILL.md

UI Animation

Tasteful UI animation with proper timing, accessibility, and performance.

Quick Start

Technique Decision:

  • Simple transition? → CSS/Tailwind (transition-*, animate-*)
  • Enter/exit with unmount? → Motion + AnimatePresence
  • Gesture-driven? → Motion springs
  • Layout changes? → Motion layout prop

Default: Start with Easing Decision Tree → Duration Guidelines → Implement → Add a11y → Verify

Core Principles

  1. Natural Motion: Mimic physics. Avoid linear easing - nothing moves at constant speed.
  2. Purposeful: Every animation must add meaning. If you can't explain its benefit, remove it.
  3. Fast: UI animations under 300ms. Hover effects under 150ms. Over 500ms feels sluggish.
  4. Interruptible: Use springs for gesture-driven animations - they handle interruption gracefully.
  5. Accessible: Always respect prefers-reduced-motion. Non-negotiable.

Workflow

Step 1: Classify Animation Type

Type Examples Technique
Micro-interaction Button press, toggle, checkbox CSS/Tailwind
Enter/Exit Modal, toast, dropdown Motion + AnimatePresence
Layout change Accordion, reorder, expand Motion layout prop
Shared element Tab indicator, card expand Motion layoutId
Gesture Drag, swipe, pull-to-refresh Motion springs

Step 2: Choose Timing

  1. Use Easing Decision Tree below to select curve
  2. Use Duration Guidelines to select timing
  3. For gestures, use Spring Animations config

Step 3: Implement

  1. Check references/recipes.md for copy-paste patterns
  2. Apply timing from Step 2
  3. Wrap unmounting elements in AnimatePresence

Use ui_to_artifact when starting from a design screenshot or mockup. Use ui_diff_check to compare expected vs implemented UI.

Step 4: Accessibility (Required)

  1. Check prefers-reduced-motion with useReducedMotion() or motion-safe:
  2. Simplify to opacity-only for reduced motion users
  3. Verify focus timing (move focus AFTER animation starts)

Step 5: Verify

  • Exit animations run (not instant unmount)
  • opacity: 0 elements have pointerEvents: none
  • Focus moves after animation starts, not before
  • Only animating transform and opacity

Easing

Decision Tree

text
What triggers the animation?
│
├─ User action (click, tap, open)?
│  └─ Use: ease-out (fast start, slow end = responsive)
│
├─ Element moving on-screen (tab switch, reorder)?
│  └─ Use: ease-in-out (accelerate then decelerate)
│
├─ Continuous/looping (spinner, marquee)?
│  └─ Use: linear (constant speed appropriate here)
│
├─ Gesture-based (drag, swipe, pull)?
│  └─ Use: Spring animation (physics-based, interruptible)
│
└─ Hover/focus effect?
   └─ Use: CSS ease, 150ms (subtle, immediate)

Quick Reference

Purpose CSS Tailwind Duration
Modal/drawer enter cubic-bezier(0.32, 0.72, 0, 1) ease-out duration-200 200ms
Modal/drawer exit cubic-bezier(0.32, 0.72, 0, 1) ease-out duration-150 150ms
On-screen movement cubic-bezier(0.4, 0, 0.2, 1) ease-in-out duration-200 200-300ms
Hover effect ease ease duration-150 150ms
Button press active:scale-[0.97] instant

Pro Curves

Name Value Use Case
Vaul (buttery) cubic-bezier(0.32, 0.72, 0, 1) Sheets, drawers, modals
Emphasized cubic-bezier(0.2, 0, 0, 1) Material Design 3
Snappy cubic-bezier(0.25, 1, 0.5, 1) Fast UI transitions

Avoid: Built-in ease-in—starts slow, feels sluggish.

Duration Guidelines

Type Duration Notes
Micro-feedback 100-150ms Button press, toggle, checkbox
Small transition 150-250ms Tooltip, icon morph
Medium transition 200-300ms Modal, popover, dropdown
Large transition 300-400ms Page transition, complex layout
Maximum <500ms Exceptions: onboarding, data viz

Key Rules:

  • Exit faster than enter: 200ms enter → 150ms exit
  • Hover = fast: Under 150ms
  • High-frequency = instant: Keyboard nav, scrolling—<100ms or none

Spring Animations

Duration-based (Recommended)

Easier to compose with other timed animations. Use visualDuration (time to visually reach target) and bounce (0 = no bounce, 1 = very bouncy).

Feel Config Use Case
Snappy { duration: 0.3, bounce: 0.15 } Tabs, buttons, quick feedback
Standard { duration: 0.4, bounce: 0.2 } Modals, menus, general UI
Gentle { duration: 0.5, bounce: 0.25 } Smooth, human-like flow

Physics-based (Legacy/Advanced)

Use when integrating with physics libraries or when precise control over spring dynamics is needed.

Feel Config Use Case
Snappy { stiffness: 400, damping: 30 } High-frequency interactions
Standard { stiffness: 300, damping: 20 } Framer Handshake convention
Gentle { stiffness: 120, damping: 14 } react-motion preset

Gotcha: stiffness/damping/mass overrides duration/bounce. Pick one approach—don't mix.

Layout Animations

The layout Prop

Add layout to animate position/size changes automatically. Use layout="position" for text (prevents distortion).

Prop Value Effect Use Case
layout={true} Animates position AND size Default for flexible elements
layout="position" Animates only translation Text/icons that shouldn't stretch
layout="size" Animates only dimensions Fixed-position expanding panels

Shared Element Transitions (layoutId)

Elements with matching layoutId animate between each other when entering/exiting.

Critical Trap: Duplicate layoutId values cause elements to teleport across the page. Use unique IDs per context or wrap in <LayoutGroup id="...">.

Layout Gotchas

  • Text distortion: Apply layout="position" to text elements
  • Border radius: Can warp during scale—Motion auto-corrects, but test it
  • SVG elements: layout doesn't work on <path>—use manual morphing

Gesture Gotchas

Problem Solution
Touch scroll conflicts dragPropagation={false}
Element snaps back Check dragConstraints + dragElastic
Momentum feels wrong dragMomentum={false} for precise UIs
One-direction only dragElastic={{ top: 0, bottom: 0.5 }}

Swipe dismiss: Check BOTH distance AND velocity—users expect flicks to work.

Accessibility

prefers-reduced-motion (REQUIRED)

tsx
import { useReducedMotion } from "motion/react"

const shouldReduce = useReducedMotion()
const variants = shouldReduce 
  ? { opacity: 1 }                    // Fade only
  : { opacity: 1, scale: 1, y: 0 }    // Full animation

Tailwind: motion-safe:animate-pulse / motion-reduce:transition-none

Best practice: Don't disable—simplify. Remove spatial movement, keep opacity.

Focus Management

  • Move focus AFTER animation starts: requestAnimationFrame(() => ref.focus())
  • Restore focus to trigger on close
  • Don't animate inside aria-live regions

Touch Targets

Standard Size Tailwind Physical
Material Design 48×48 dp min-h-12 min-w-12 ~9mm (recommended)
Apple HIG 44×44 pt min-h-11 min-w-11 ~7mm
WCAG 2.2 (AA) 24×24 px min-h-6 min-w-6 ~5mm (minimum)

Why? Average adult finger pad is ~9mm. Targets below 7mm cause "fat finger" errors. Use Material's 48dp for cross-platform; Apple's 44pt is iOS-specific minimum.

Performance

Golden Rules

  1. Only animate transform and opacity—GPU-accelerated
  2. Never animate: width, height, top, left, margin, padding
  3. will-change sparingly—only during animation, remove after
  4. Blur thresholds:
    • ≤10px: Safe for animation
    • 11-20px: May cause jank on mobile/4K—test thoroughly
    • 20px: Avoid for real-time effects; use pre-blurred images instead

  5. Prefer CSS over JS for simple transitions

Key Traps

  • Height animation: Use layout prop, not animate={{ height }}
  • Invisible but clickable: opacity: 0 still receives clicks—add pointerEvents: "none"
  • will-change everywhere: Causes layer explosion, mobile crashes

See references/recipes.md for detailed examples.

Examples

Copy-paste patterns organized by category in references/recipes.md:

  • Common UI Patterns: Button press, modal enter/exit, error shake, staggered lists, accordion
  • Touch & Interaction: Accessible touch targets, hover on touch devices, instant tooltips
  • Layout Animations: layout prop, layoutId shared elements, collision fixes
  • Radix UI Integration: forceMount pattern, asChild, origin-aware popovers
  • Accessibility: Focus timing, focus restoration, reduced motion variants
  • Performance: Height animation (use layout), invisible-but-clickable fix, will-change
  • Exit Patterns: popLayout with forwardRef, SSR hydration (initial={false})
  • Gestures: Swipe dismiss with velocity check, elastic drag boundaries

AnimatePresence

Mode Behavior Use Case
sync (default) Simultaneous enter/exit Crossfades, overlays
wait Exit completes before enter Page transitions, tabs
popLayout Exiting elements leave flow List removals (with layout)

Exit Animation Trap

Exit animations require AnimatePresence—without it, unmount is instant:

tsx
// ❌ Exit never runs
{isOpen && <motion.div exit={{ opacity: 0 }}>...</motion.div>}

// ✅ Wrap in AnimatePresence
<AnimatePresence>
  {isOpen && <motion.div exit={{ opacity: 0 }}>...</motion.div>}
</AnimatePresence>

SSR: Use <AnimatePresence initial={false}> to prevent animation on page load.

Anti-patterns

Don't Do Instead Why
scale(0) start scale(0.9) or higher Avoids "popping" effect
linear for UI ease-out or springs Linear feels robotic
Animations >500ms Keep under 300ms Feels sluggish
Same tooltip delay First: 400ms, subsequent: 0ms User mental model
Skip reduced-motion Always motion-safe: Accessibility
Animate layout props Use transform: scale() Performance
Excessive bounce bounce: 0-0.2 Unprofessional

tailwindcss-animate

Tailwind v4: Define keyframes via @theme in CSS, not config.

Category Classes
Enter animate-in fade-in zoom-in-95 slide-in-from-top
Exit animate-out fade-out zoom-out-95 slide-out-to-top
Timing delay-150 duration-500
Fill Mode fill-mode-forwards fill-mode-backwards

Integration with Other Skills

When Skill Why
After implementing code-quality Ensure code passes checks
Reusable patterns docs-write Document component API
Before committing git-commit Use feat(ui): or style:
Integration issues search Look up latest patterns

Output

  • Artifacts: Code changes only (no .ada/ outputs)
  • Modifications: Component animations, CSS/Tailwind styles, Motion configs
  • Type: Workflow skill (guidance only, no scripts)

References

Internal

  • references/recipes.md - Copy-paste patterns, integration examples, detailed traps

External

Expand your agent's capabilities with these related and highly-rated skills.

LukasStrickler/ai-dev-atelier

resolve-pr-comments

Resolve bot review comments (CodeRabbit, Copilot, Gemini) on GitHub PRs using subagents. Use when: (1) User asks to 'review PR comments' or 'resolve PR comments', (2) User says 'work through PR N comments' or 'handle bot comments', (3) Need to triage CodeRabbit/Copilot/Gemini review comments, (4) Processing PR feedback at scale, (5) Want to see what's already fixed vs still pending. NOT for: creating PRs, reviewing code yourself, writing new reviews. Triggers: review PR comments, resolve PR comments, work through PR comments, handle bot comments, process CodeRabbit comments, triage PR feedback, fix PR review issues, resolve bot comments, pr comment resolver.

2 0
Explore
LukasStrickler/ai-dev-atelier

tdd

Strict Red-Green-Refactor workflow for robust, self-documenting code. Discovers project test setup via codebase exploration before assuming frameworks. Use when: (1) Implementing new features with test-first approach, (2) Fixing bugs with reproduction tests, (3) Refactoring existing code with test safety net, (4) Adding tests to legacy code, (5) Ensuring code quality before committing, (6) When tests exist but workflow unclear, or (7) When establishing testing practices in a new project. Triggers: test, tdd, red-green-refactor, failing test, test first, test-driven, write tests, add tests, run tests.

2 0
Explore
LukasStrickler/ai-dev-atelier

use-graphite

Manage stacked PRs with Graphite CLI (gt) instead of git push/gh pr create. Auto-detects Graphite repos and blocks conflicting commands with helpful alternatives. Use when: (1) About to run git push or gh pr create in a Graphite repo, (2) Creating a new branch for a feature, (3) Submitting code for review, (4) Large changes that should be split into reviewable chunks, (5) Hook blocks your git command and suggests gt equivalent. NOT for: repos not initialized with Graphite, git add/commit/status/log. Triggers: git push blocked, gh pr create blocked, create branch, submit PR, stacked PRs, split large PR, gt create, gt submit, graphite workflow.

2 0
Explore
LukasStrickler/ai-dev-atelier

git-commit

Write clear git commits with Conventional Commits format. Detects project conventions from history and config. Guides commit granularity. Use when: (1) Completing working code, (2) Code builds and tests pass, (3) Ready to save, (4) Before pushing, (5) After review feedback. Triggers: automatically when finishing commitable work that builds and passes tests.

2 0
Explore
LukasStrickler/ai-dev-atelier

code-review

Review code changes using CodeRabbit CLI - supports uncommitted files (task mode) or all PR files vs main branch (pr mode). Catches bugs, security issues, and code quality problems before committing or when reviewing pull requests. Use when: (1) Reviewing uncommitted changes before committing (task mode), (2) Reviewing all changed files in a PR against main branch (pr mode), (3) Working on subtasks and want to check progress, (4) Need feedback on work-in-progress code, (5) Preparing PR for merge, (6) When CodeRabbit review is needed, (7) For bug detection and security scanning, or (8) For automated code quality assessment. Triggers: review code, check code quality, review changes, code review, review PR, check for bugs, security scan, review uncommitted, finalize code, pre-commit review.

2 0
Explore
LukasStrickler/ai-dev-atelier

image-generation

Generate, edit, and upscale AI images. Use when creating visual assets for apps, websites, or documentation. FREE Cloudflare tier for iterate generation (~96/day), Fal.ai for paid tiers. Four quality tiers (iterate/default/premium/max). Supports text specialists, multi-ref editing, SVG, background removal. Triggers: generate image, create image, edit image, upscale, logo, picture of, remove background.

2 0
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results