animation

SKILL.md

Animation Implementation with Motion

Use the Motion library (https://motion.dev) for all animation work.

Quick Start

React (Primary):

import { motion } from "motion/react"

// Basic animation
<motion.div animate={{ opacity: 1, y: 0 }} />

// With transition config
<motion.div
  animate={{ x: 100 }}
  transition={{ type: "spring", stiffness: 100 }}
/>

Core Patterns

1. Spring Physics (Preferred)

<motion.div
  animate={{ scale: 1 }}
  transition={{
    type: 'spring',
    stiffness: 260,
    damping: 20,
  }}
/>

Spring presets:

  • Gentle: stiffness: 120, damping: 14
  • Wobbly: stiffness: 180, damping: 12
  • Stiff: stiffness: 300, damping: 20

2. Gesture Interactions

<motion.div
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  drag="x"
  dragConstraints={{ left: -100, right: 100 }}
/>

3. Layout Animations

<motion.div layout>{/* Content that changes position/size */}</motion.div>

4. Scroll-Linked Effects

import { useScroll, useTransform } from "motion/react"

const { scrollYProgress } = useScroll()
const opacity = useTransform(scrollYProgress, [0, 1], [1, 0])

<motion.div style={{ opacity }} />

5. Stagger Children

<motion.ul
  variants={{
    visible: { transition: { staggerChildren: 0.07 } },
  }}
>
  {items.map((item) => (
    <motion.li
      key={item}
      variants={{
        hidden: { opacity: 0, y: 20 },
        visible: { opacity: 1, y: 0 },
      }}
    />
  ))}
</motion.ul>

6. Enter/Exit Animations

import { AnimatePresence } from 'motion/react';

<AnimatePresence>
  {show && <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} />}
</AnimatePresence>;

Animation Properties

Transform (GPU-accelerated, performant):

  • x, y, z - Translate
  • scale, scaleX, scaleY - Scale
  • rotate, rotateX, rotateY, rotateZ - Rotation
  • skew, skewX, skewY - Skew

Visual (use sparingly, can affect performance):

  • opacity
  • background, backgroundColor
  • color
  • borderRadius

SVG-specific:

  • pathLength - For path drawing animations
  • pathOffset - Offset the path
  • pathSpacing - Spacing between dashes

Accessibility

Always respect user preferences:

<motion.div
  animate={{ x: 100 }}
  transition={{
    type: 'spring',
    // Disables animation if user prefers reduced motion
    duration: 0,
  }}
/>

Motion automatically handles prefers-reduced-motion. Springs become instant transitions.

Performance Tips

  1. Animate transforms/opacity only when possible (GPU-accelerated)
  2. Use layout prop instead of animating width/height manually
  3. Avoid animating during scroll when possible
  4. Use will-change: transform for complex animations (Motion handles this)
  5. Limit simultaneous animations - stagger instead of all-at-once

Design Principles (Brief)

When to Animate

  • State transitions (loading → success)
  • Spatial changes (entering/exiting view)
  • Drawing attention (sparingly)
  • Confirming user action

When NOT to Animate

  • Repeated actions after first occurrence
  • Performance-critical paths
  • User-controlled scrolling
  • Every single interaction (restraint matters)

Timing Guidelines

  • Micro-interactions: 150-250ms
  • Panel/modal transitions: 200-300ms
  • Page transitions: 300-500ms
  • Springs: Let physics determine duration

Spring vs Duration

  • Use springs for: Interactive elements, gestures, layout changes
  • Use duration for: Intentional sequences, choreography, loaders

See principles.md for detailed animation philosophy.

Common Patterns

Loading state:

<motion.div
  animate={{ rotate: 360 }}
  transition={{
    repeat: Infinity,
    duration: 1,
    ease: 'linear',
  }}
/>

Toast notification:

<motion.div
  initial={{ x: 400, opacity: 0 }}
  animate={{ x: 0, opacity: 1 }}
  exit={{ x: 400, opacity: 0 }}
  transition={{ type: 'spring', stiffness: 300, damping: 30 }}
/>

Drawer:

<motion.div
  initial={{ x: '-100%' }}
  animate={{ x: 0 }}
  exit={{ x: '-100%' }}
  transition={{ type: 'spring', damping: 25 }}
/>

Accordion:

<motion.div
  animate={{ height: isOpen ? 'auto' : 0 }}
  transition={{ type: 'spring', bounce: 0 }}
  style={{ overflow: 'hidden' }}
/>

Resources

Quick Troubleshooting

Animation not running?

  • Check if element is conditionally rendered (use AnimatePresence)
  • Verify target values are different from initial values
  • Check for CSS that might override (e.g., !important)

Performance issues?

  • Stick to transforms and opacity
  • Use layout prop instead of animating dimensions
  • Check browser DevTools Performance tab

Layout animations flickering?

  • Ensure parent has position: relative
  • Add layout to both parent and child if needed
  • Check for conflicting CSS transitions

Notes

  • Motion is MIT licensed, production-ready
  • Hybrid engine: 120fps, GPU-accelerated
  • TypeScript support built-in
  • Tree-shakable for optimal bundle size
  • Works with React 18+ (including Suspense)
Weekly Installs
3
First Seen
Jan 29, 2026
Installed on
claude-code3
mcpjam2
kilo2
junie2
windsurf2
zencoder2