Use when an interface moves and the movement has to feel right — durations and easing, what must never animate, fixing motion that reads sluggish, cheap or janky, and reduced-motion. Web and native. NOT the visual system (that is `design`), NOT the graded critique (that is `design-loop`).
npx skills add https://github.com/ericrisco/rsc-harness --skill motion-craft
Motion is not decoration laid over an interface. It is the interface **explaining what just
happened**: what appeared, what it came from, what is still loading, what the user just did. When
motion feels wrong the complaint is almost never "the curve is off" — it is "this feels cheap", or
"slow", or "I don't know what happened". Those are the symptoms this skill exists to convert into
decisions.
Every animation answers a question the user is already asking. If you cannot name the question,
delete the animation — it is costing time and attention and returning nothing.
| The user is asking | The motion that answers it |
| --- | --- |
| "Where did this come from?" | It enters from its origin, not from nowhere |
| "Is it working?" | Immediate feedback, under 100ms, even before the result |
| "What did I just do?" | The changed thing moves; nothing else does |
| "Where did it go?" | It exits toward where it can be found again |
| nothing | no animation |
That table is the whole method. Everything below is how to honour it without shipping something
that janks.
Movement is read as *slow* long before it is read as *long*. The usable range is narrower than most
people expect, and the mistake is almost always too slow, not too fast.
| What moves | Range | Why |
| --- | --- | --- |
| State on an element already on screen (hover, toggle, press) | 100–150ms | It must feel like a response, not an event |
| Something entering or leaving in place (menu, tooltip, toast) | 150–250ms | Long enough to be seen, short enough not to be waited for |
| A region rearranging (list reflow, panel) | 250–350ms | Bigger travel needs more time to stay legible |
| A full view transition | 300–400ms | The ceiling. Past 400ms it is a wait, not a transition |
Two rules that come from those numbers, not from taste:
them watch the decision leave is the single most common way an interface feels sluggish.
time. If a value grows past 400ms because the element crosses the screen, the layout is the
problem, not the timing.
ease-out family). The user'sattention is already there; arriving quickly and settling reads as responsive.
ease-in family). It matches how the eye lets go.ease-in-out family).Linear is for one thing only: continuous, non-positional change — a progress bar filling, a
spinner rotating, a colour crossfade. Linear on anything that moves in space reads as mechanical,
because nothing physical starts at full speed.
Springs are worth reaching for when the motion should feel *physical* — dragging, dismissing,
anything the user's finger or pointer is still in contact with. They are the wrong tool for
appearing and disappearing, where a bounce reads as indecision.
This is where most jank comes from, and it is not a matter of degree.
to recompute geometry. Animate transform and opacity, which do not.
transition: all. It is the shortest path to animating layout by accident. List theproperties.
mid-motion. An animation that must finish before the user may act has become a modal dialog.
cannot tell which one mattered.
A real share of people have vestibular conditions for which large movement is nauseating, and they
have told their operating system so. Honouring it is not optional and it is not a fallback to
nothing:
An implementation with no reduced-motion branch is unfinished, the same way an interface with no
error state is unfinished.
The complaint names the symptom; this maps it to a cause.
| Complaint | Usually | Fix |
| --- | --- | --- |
| "Sluggish" | Duration too long, or the exit matches the entrance | Cut to the range above; make exits faster |
| "Cheap" / "amateur" | Linear easing on positional movement, or bounce on entrances | Match curve to direction |
| "Janky" / "stutters" | Animating layout properties | Move to transform and opacity |
| "Distracting" | More than one thing moving per event | Animate only what changed |
| "I don't know what happened" | Motion with no origin or destination | Move it from where it came from |
| "Nice, but I'd turn it off" | No reduced-motion branch, or motion that repeats | Honour the setting; never loop what is not loading |
| If you're about to… | Reality / Fix |
| --- | --- |
| Add motion because the screen feels static | Static is not a defect. Motion with no question to answer is noise with a frame cost. |
| Copy a duration from a design you liked | You copied the number without its distance and its context. Take the range, verify against the feel. |
| Animate a list so every item cascades in | Stagger past ~4 items becomes a queue the user waits through. Cap it, or drop it. |
| Use a spring for a menu appearing | A bounce on an entrance reads as indecision. Springs are for what the pointer is still touching. |
| Ship motion without checking reduced-motion | It is not an edge case. Unchecked means unfinished. |
| Reach here for the visual system | Type, colour, spacing and composition are ../design/SKILL.md. This skill only moves what that one placed. |
../design/SKILL.md — the visual system this motion serves.../design-loop/SKILL.md — the graded critique that judges a finished screen, motion included.../design-dna/SKILL.md — turning a look, motion rules included, into a reusable identity.../accessibility/SKILL.md — the wider ground reduced-motion sits in.Take ericrisco/motion-craft from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.