Auto-Editor Agent
A self-improving motion-ad agent. It researches current trends, analyzes your media, drafts a plan, critiques itself, and refines — all visible live below.
Why Motion Matters
Motion is communication. It tells the user where things came from, where they're going, and how the system feels under their fingers.
Bad motion is jarring, slow, or distracts. Good motion is invisible until you remove it. Great motion makes the product feel alive.
This guide is a complete tour of the craft — from physical intuition to code patterns to performance budgets.
The 12 Principles of Animation
Disney's foundational rules from The Illusion of Life. They predate the web by 80 years yet still govern every great UI motion today.
Easing Lab
Easing is the soul of motion. A bezier curve dictates how a value moves between two points — and changes everything emotionally.
Use easeOut for things appearing (snappy entry), easeIn for things leaving, and easeInOut for in-place changes. [0.22, 1, 0.36, 1] is the gold-standard "smooth confident" curve.
Timing & Rhythm — 間 (Ma)
Japanese has a word for the space between: 間 (ma). It's the negative space of time — the silence that lets the music breathe.
Standard: 200–300ms · Complex: 375ms · Large surface: 500ms
UIView default 0.25s · Spring response 0.5s · Damping 1.0
Spring Physics
Springs simulate real-world physics. Instead of fixed durations, you define stiffness, damping, and mass — the system finds its own time.
transition={{ type: "spring", stiffness: 200, damping: 20, mass: 1 }}Orchestration · Stagger & Choreography
Animating one element is easy. Animating ten in sequence so the eye flows naturally — that's choreography. The key is stagger.
{items.map((it, i) => (
<motion.div
key={it.id}
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: i * 0.08 }}
/>
))}Scroll-Driven Motion
Tying motion to the scrollbar transforms a page into a film. useScroll + useTransform map scroll progress to any value.
const { scrollYProgress } = useScroll({ target: ref });
const x = useTransform(scrollYProgress, [0, 1], ["-50%", "50%"]);
const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.6, 1.2, 0.6]);Page Transitions
AnimatePresence lets you animate components as they leave the tree — the secret to elegant page transitions.
Code Patterns
The four patterns you'll use 90% of the time. Learn these by heart.
const fade = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0, transition: { duration: 0.4 } }
};
<motion.div variants={fade} initial="hidden" animate="show" /><motion.div layout transition={{ type: "spring", stiffness: 300 }}>
{/* re-renders that change size/position auto-animate */}
</motion.div><motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
drag dragConstraints={{ left: 0, right: 200 }}
/><AnimatePresence>
{open && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>Performance Budget
60fps means each frame has 16.67ms. After React, paint, and composite, you have ~6ms of motion budget per frame. Every CSS property you touch matters.
The Full Stack of Motion
Motion isn't one library — it's a stack. From the GPU compositor up to LLM-generated keyframes. Master each layer and you can ship anything.