Implement animations using the Motion library. Use when adding motion, transitions, gestures, scroll effects, or interactive animations to components...
Use the Motion library (https://motion.dev) for all animation work.
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 }}
/>
<motion.div
animate={{ scale: 1 }}
transition={{
type: 'spring',
stiffness: 260,
damping: 20,
}}
/>
Spring presets:
stiffness: 120, damping: 14stiffness: 180, damping: 12stiffness: 300, damping: 20<motion.div
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
drag="x"
dragConstraints={{ left: -100, right: 100 }}
/>
<motion.div layout>{/* Content that changes position/size */}</motion.div>
import { useScroll, useTransform } from "motion/react"
const { scrollYProgress } = useScroll()
const opacity = useTransform(scrollYProgress, [0, 1], [1, 0])
<motion.div style={{ opacity }} />
<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>
import { AnimatePresence } from 'motion/react';
<AnimatePresence>
{show && <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} />}
</AnimatePresence>;
Transform (GPU-accelerated, performant):
x, y, z - Translatescale, scaleX, scaleY - Scalerotate, rotateX, rotateY, rotateZ - Rotationskew, skewX, skewY - SkewVisual (use sparingly, can affect performance):
opacitybackground, backgroundColorcolorborderRadiusSVG-specific:
pathLength - For path drawing animationspathOffset - Offset the pathpathSpacing - Spacing between dashesAlways 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.
layout prop instead of animating width/height manuallywill-change: transform for complex animations (Motion handles this)See principles.md for detailed animation philosophy.
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.md for curated animation.dev lessons and vaultAnimation not running?
!important)Performance issues?
layout prop instead of animating dimensionsLayout animations flickering?
position: relativelayout to both parent and child if needed