Export

The Motion dialect

Your component comes back with initial, animate and a transition per property on each element you animated. A spring that settles inside its own segment exports as a native spring config instead of sampled keyframes, so Motion runs the spring you designed.

A transition per property
Motion lets each animated value carry its own transition, so x can spring while opacity eases. Of the three dialects, that’s the closest to how the timeline works.
Springs stay springs
A two-keyframe spring that comes to rest within its span becomes type: "spring" with the stiffness, damping and mass you set. Nothing is sampled, so the code reads like something a person wrote.
…until they can’t
A spring cut short by the next keyframe has no native equivalent, since a spring config describes a settle, not a cut. Those export as a values array with explicit times, sampled closely enough to stay within tolerance. Where the cut lands mid-flight, the last two stops share a time: the spring holds until that moment and jumps, as the timeline does, instead of ramping into the target across its final sample.
Rest thresholds are pinned where it matters
Motion decides a spring has finished using a window scaled to the initial delta. Where that window is coarser than 1% of the travel, the export sets the engine’s own thresholds instead. Otherwise a 12° skew would get a 0.5° threshold, larger than its overshoot.
Interaction states ride along
Hover, press and focus become whileHover and friends on the same element the timeline animates. They coexist because a state is a target, not a keyframe.
Your component, with the motion written in
Every part you animated comes back as its own tag, like motion.li or motion.div, where it stands in your markup, with its attributes kept and the animation added beside them. A pasted module comes back whole: its imports, helpers and state as they were, with import { motion } added once. Copy it, paste it over the component, and you’re done.
The component animates itself
The component’s own animation goes on its root element, where CSS and GSAP put it too. Only a component with more than one root, or one whose root element is also a part you animated, gets a motion.div around it.
Where it won’t guess
A part rendered by a map, a condition or a component your paste defines isn’t in your markup as written, and neither is one whose markup changed after you picked it. Those come as a named props object and the one line that uses it (<motion.li {...row}>), instead of a guess at which element was meant.
It type-checks
Variants and props objects end in satisfies Variants or satisfies MotionProps, which keeps their eases and spring types exact for TypeScript. Without it, ease: "easeOut" widens to a string Motion rejects. In a .jsx file, delete those two words.
Scroll, reduced motion and view transitions too
The exports that need a hook are written into your component the same way: useScroll or useReducedMotion at the top of its body, the imports it lacks added to the ones it has, and the props on its root. For a component with picked parts, reduced motion picks each part’s props per render (variants={reduce ? itemReduced : item}). An arrow component that returns its markup directly gets a body to hold the hook.
Where one paste stops
A ref already on your root, or a spread that might carry one, puts the scroll export on a motion.div around it. If a hook’s name is already used for something else, or the export is a cross-fade on a pasted module, the component is left for you to fill in. A cross-fade needs a viewKey prop, and your component’s signature isn’t the export’s to change.