motion-react
Skill2 starsChanged 3 months agoMITView on GitHub
Use when adding animation to a React app with the Motion library (the framer-motion successor: npm package `motion`, import `motion/react`) — enter/exit animations, variants and stagger, AnimatePresence, layout and shared-element transitions, animated number tickers, gesture states — or when deciding whether a job needs Motion at all versus plain CSS/Tailwind transitions or AutoAnimate. Covers reduced-motion accessibility (MotionConfig, useReducedMotion, WCAG 2.3.3/2.2.2) as a first-class requirement, performance discipline (transform/opacity only), motion restraint for data-dense product UI, Radix/shadcn and router integration, and keeping tests stable (MotionGlobalConfig.skipAnimations). Keywords: motion, framer-motion, animation, AnimatePresence, layout animation, micro-interactions, reduced motion, page transitions, stagger, spring.
- Installs packages
2 other projects use a version of this.
Adopted by
Most recently taken up by
- davidanthonyn/claude-skillstheir own version, first seen Oct 20, 2026
- FelipeAngeli/skillstheir own version, first seen Apr 10, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- FelipeAngeli/skills★ 2same name
- davidanthonyn/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository77 other files it gives its agents.
- alembicSkill
- atlassian-rest-opsSkill
- authoring-api-referenceSkill
- authoring-api-specSkill
- authoring-architecture-docSkill
- authoring-data-modelSkill
- authoring-design-systemSkill
- authoring-developer-guideSkill
- authoring-feature-specSkill
- authoring-hi-fiSkill
- authoring-prdSkill
- authoring-release-runbookSkill
- authoring-technical-designSkill
- authoring-test-planSkill
- authoring-user-flowsSkill
- authoring-user-guideSkill
- authoring-wireframesSkill
- biomeSkill
- cloudflare-pages-opsSkill
- code-prior-art-surveySkill
- content-template-gatewaySkill
- design-reviewSkill
- external-content-sanitizerSkill
- github-cli-opsSkill
- integrations-prior-art-surveySkill
- jenkins-rest-opsSkill
- market-competitive-prior-art-surveySkill
- ml-prior-art-surveySkill
- netlify-opsSkill
- openapi-ts-clientSkill
- platform-ecosystem-prior-art-surveySkill
- polyglot-git-hooksSkill
- project-document-discoverySkill
- pydantic-v2Skill
- python-monorepo-architectureSkill
- react-component-testingSkill
- regulatory-prior-art-surveySkill
- rest-api-designSkill
- reviewing-api-referenceSkill
- reviewing-api-specSkill
- reviewing-architecture-docSkill
- reviewing-code-prior-art-surveySkill
- reviewing-data-modelSkill
- reviewing-design-systemSkill
- reviewing-developer-guideSkill
- reviewing-document-discoverySkill
- reviewing-document-setSkill
- reviewing-feature-specSkill
- reviewing-hi-fiSkill
- reviewing-integrations-prior-art-surveySkill
- reviewing-market-competitive-prior-art-surveySkill
- reviewing-ml-prior-art-surveySkill
- reviewing-platform-ecosystem-prior-art-surveySkill
- reviewing-prdSkill
- reviewing-regulatory-prior-art-surveySkill
- reviewing-release-runbookSkill
- reviewing-scale-prior-art-surveySkill
- reviewing-security-prior-art-surveySkill
- reviewing-technical-designSkill
- reviewing-test-planSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 200
Respect reduced motion: Every Motion-using app sets MotionConfig reducedMotion="user" (or an equivalent explicit strategy) at the root.
- Very specific: line 216
Import from
"motion/react": Do not add framer-motion to a new project. - Distinctive: line 228
Prefer the simplest sufficient tier (Step 1) before reaching for Motion.
- Very specific: line 265
"AutoAnimate is beneath us — rewrite the list in Motion.": If add/remove/move is all the list needs, one ref beats thirty lines of variants.
- Distinctive: line 267
"Copy the framer-motion snippet from that 2023 blog post.": Verify against current docs.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
motion-react — Motion for React
Overview
Implements UI animation in React with Motion — the library previously published as
framer-motion, independent since late 2024 and published as the npm package motion
(import from "motion/react"). The skill covers the DOM product-UI animation surface:
declarative enter/exit, variant orchestration, layout and shared-element transitions,
motion values and number tickers, and gesture states — with three non-negotiables woven
through: reduced-motion accessibility, compositor-friendly performance, and
restraint (purposeful, short, consistent motion — especially in data-dense tools).
It also owns the "do I even need Motion?" decision: many jobs are better served by plain
CSS or a one-line AutoAnimate call.
When to activate
- ✅ Adding enter/exit/list animations, page or view transitions, shared-element moves, animated counters, or gesture feedback to a React SPA.
- ✅ Migrating or writing code that references
framer-motion(the old package) — this skill teaches the currentmotionidioms. - ✅ Wiring reduced-motion support, or auditing existing animation for accessibility/performance.
- ✅ Choosing between Motion, CSS/Tailwind transitions, and AutoAnimate for a given interaction.
Do NOT activate when:
- The task is animated illustrations / Lottie files — that is imagery, not UI motion (a dedicated illustrations skill owns it).
- The task is video rendering (Remotion) or scroll-storytelling/parallax marketing pages — different genre; only
whileInViewbasics are covered here. - The product's motion design language (which durations/easings a specific app adopts) is being decided — that is a design-system decision; this skill supplies the vocabulary and constraints.
Workflow
Step 1: Choose the right tool — most animations don't need Motion
| Job | Reach for | Why |
| Hover/focus color, opacity, small scale | Plain CSS / Tailwind transition-* | Zero JS, zero bundle, GPU-friendly |
| Open/close styling on Radix-based components (accordions, popovers, dialogs) | CSS keyed off Radix data-state attributes | The primitive already exposes state; CSS animates it |
| List add / remove / reorder in an internal tool | AutoAnimate — one useAutoAnimate() ref on the parent | Zero-config, animates child add/remove/move, respects prefers-reduced-motion automatically |
Exit animations on unmount, orchestrated sequences, shared-element moves, springs, number tickers, drag / drag-to-reorder (Reorder components) | Motion | Needs JS lifecycle control CSS cannot express |
| Browser-native view morphs (same-document, or cross-document/MPA) | View Transitions API | Named for awareness; for view/route swaps in a React SPA, AnimatePresence covers the equivalent (whole-document morphs like a theme crossfade remain VTA-only) |
Escalate down the table only when the simpler tier genuinely cannot do the job.
Step 2: Install and set the app-level posture
npm install motionimport { motion, MotionConfig } from "motion/react"
// App root — respect the user's OS reduced-motion setting everywhere:
<MotionConfig reducedMotion="user">
<App />
</MotionConfig>- Package is
motion; React entry is"motion/react". React 18+ (docs state 18.2; the peer range is^18.0.0 || ^19.0.0). Anything importingframer-motionis the pre-rename package — same lineage, but new projects usemotionand current docs/idioms live under that name. MotionConfig reducedMotionaccepts"user"(respect the OS setting),"always"(force-reduce; debugging),"never"(default). Under reduction, Motion disables transform and layout animations while keeping opacity/color animations — usually exactly the right degradation. Set"user"at the root as the default posture; seereferences/a11y-and-restraint.mdfor the full contract.- The reduced-bundle wiring is one wrapper:
<LazyMotion features={domAnimation} strict><m.div animate={{ opacity: 1 }} /></LazyMotion>. - React Server Component frameworks:
motioncomponents are client components — add a"use client"boundary (or import frommotion/react-client); a plain Vite SPA needs neither. - Bundle-sensitive apps:
LazyMotion+ themcomponent (import * as m from "motion/react-m") renders for ~4.6 kB initially (vs ~34 kB for fullmotion), with features (domAnimation) loaded sync or — for the full saving — async after hydration;strictonLazyMotionthrows if a fullmotioncomponent sneaks in.
Step 3: Core animation
<motion.div
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2, ease: "easeOut" }}
/>initial→animateruns on mount;exitruns on unmount only insideAnimatePresence(Step 5).transitionpicks the model:type: "tween"(duration + easing — UI default) ortype: "spring"(physical; use for gestures/drag, sparingly for entrances). Keyframes: pass arrays (animate={{ x: [0, 100, 0] }});nullas the first keyframe means "current value".- Gesture states:
whileHover,whileTap,whileFocus,whileDrag,whileInView— values revert when the gesture ends. Prefer CSS for hover-only styling (Step 1); use these when the gesture must coordinate with other animated values. - Product-UI durations: 150–300 ms for micro-interactions, ≤ 400 ms for larger transitions. Longer reads as lag, not polish.
Step 4: Variants — orchestrate parent and children
import { motion, stagger } from "motion/react"
const list = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { when: "beforeChildren", delayChildren: stagger(0.05) },
},
}
const item = { hidden: { opacity: 0, y: 4 }, visible: { opacity: 1, y: 0 } }
<motion.ul variants={list} initial="hidden" animate="visible">
{rows.map(r => <motion.li key={r.id} variants={item} />)}
</motion.ul>- Variant names flow down: children with
variantsanimate when the parent's state changes — no prop drilling. - Orchestration lives in the parent's
transition:when: "beforeChildren" | "afterChildren", anddelayChildren: stagger(interval)— the current idiom, available sincemotion12.22.0 (staggerChildren/staggerDirectionwere deprecated in 12.21.0). On older installs (framer-motion, early 12.x)staggerChildren: 0.05still works andstagger()-in-delayChildrenis not supported (the option was a plain number there) — bump the package before migrating the idiom. - Dynamic variants: a variant can be a function of
custom(e.g. per-index delay).
Step 5: AnimatePresence — exit animations
import { AnimatePresence, motion } from "motion/react"
<AnimatePresence mode="popLayout">
{rows.map(r => (
<motion.div key={r.id} exit={{ opacity: 0, x: -8 }} layout />
))}
</AnimatePresence>- Works by watching its direct children; every child needs a stable, unique
key(array indices break exit animations — the classic failure). mode:"sync"(default — in/out simultaneously),"wait"(out fully before in; one child at a time — right for view/route swaps),"popLayout"(exiting elements pop out of layout flow so siblings reflow — right for lists; the parent needs non-staticposition).- In-place content swaps (skeleton→content, tab panels): with
"wait", match the two children's dimensions or the gap flashes; when dimensions differ, crossfade in place via"popLayout"or a grid-stack/absolute overlay — and pair the container withlayoutif the size change itself should animate rather than snap. initial={false}skips mount animation for children present at first render.onExitCompletefires when all exits finish.- Exiting components cannot receive prop updates — for direction-aware exits (carousels,
paginated views), pass the direction via AnimatePresence's
customprop and read it withusePresenceData(or variantcustom) inside the child. - AnimatePresence must wrap the conditional — never be inside it.
Step 6: Beyond the core — load the reference that matches the job
- Layout animations,
layoutIdshared elements,LayoutGroup, distortion fixes →references/layout-and-shared-elements.md - Motion values,
useTransform/useSpring, imperativeanimate()/useAnimate, animated number tickers for stat tiles →references/values-and-imperative.md - The full reduced-motion contract, WCAG mapping, reduce-vs-keep table, motion-restraint
tokens →
references/a11y-and-restraint.md - Radix/shadcn integration (
forceMount), Tailwind boundaries, router page transitions, the AutoAnimate worked example, and testing (MotionGlobalConfig.skipAnimations, Playwright reduced-motion) →references/integration-and-testing.md
Rules
Hard rules (never violate):
- Respect reduced motion. Every Motion-using app sets
MotionConfig reducedMotion="user"(or an equivalent explicit strategy) at the root. Never ship large translations, zooms, parallax, or auto-playing motion that ignores the OS preference (WCAG 2.3.3; autoplaying5 s motion needs a pause control per WCAG 2.2.2).
- Animate
transformandopacity, not layout-inducing properties. Never animatewidth/height/top/left/margins directly — use thelayoutprop (which animates via transforms) or scale; cheap non-layout properties (color/background, SVG stroke values) are fine. Scale-based fills (progress bars, meters) need an explicit transform origin (originX: 0for a left-anchored fill) — the default is center. One sanctioned exception: expand/collapse reveals (accordion, disclosure) animateheight: 0 ↔ "auto"withoverflow: hidden— scale distorts text andlayoutcan't clip-reveal; keep it short and user-initiated. Note reduced motion does NOT auto-reduce it (only transform/layout animations are disabled) — if the reveal displaces substantial content, gate it withuseReducedMotion()to snap open instead. - Stable keys inside AnimatePresence. Array indices as keys silently break exit animations.
- Import from
"motion/react". Do not addframer-motionto a new project; do not mix both packages. - Motion must be purposeful. Animation communicates state change, spatial relationship, or feedback — decorative-only animation in a product UI is a defect, not polish.
Preferences (override-able):
- Micro-interactions 150–300 ms; route/page swaps ≤ 200 ms; other view-level transitions ≤ 400 ms (the outer bound, not the target).
- Tweens for UI state changes; springs for gesture-driven/physical interactions.
- Centralize durations/easings as design tokens rather than scattering literals.
- Prefer the simplest sufficient tier (Step 1) before reaching for Motion.
Gotchas
- Exit animation never plays: the element isn't a direct child of
AnimatePresence, its key is unstable, or theAnimatePresenceitself unmounts with the element. Fix the tree, not the animation. - Old-package drift: tutorials and LLM completions frequently emit
framer-motionimports,staggerChildren, ormotion(Component)-era idioms. Current:motionpkg,delayChildren: stagger(), andmotion.create(Component)to wrap a custom component (it must expose its ref —forwardRefon React 18, the plainrefprop on React 19); check the live docs when an API looks dated. popLayoutneeds positioning: exiting elements are absolutely positioned; astatic-positioned parent misplaces them.- Layout animation distorts rounded corners/shadows: set
borderRadius/boxShadowviastyle(or animate them) so Motion can scale-correct; give stretching children their ownlayoutprop. - Springs on mount feel bouncy-slow: physics-configured springs
(stiffness/damping) derive their own settle time and ignore duration expectations;
use a duration-based spring (
type: "spring", duration, bounce) or a 200 ms tween for entrances. - Motion values don't re-render React: rendering
{x.get()}in JSX goes stale — render the motion value as amotionelement child or subscribe viauseMotionValueEvent. - Tests hang or flake on animations: set
MotionGlobalConfig.skipAnimations = truein the test setup and assert end-states (see the integration reference). - jsdom has no layout: layout animations and
whileInViewneed real measurements; unit-test the state logic, e2e-test the visuals.
Anti-patterns
- "Animate everything — it looks premium." Data-dense tools earn polish through a few consistent, short, purposeful animations; motion noise slows comprehension.
- "Skip reduced-motion for now, add it later." It's a root-level one-liner when done first and an audit when done later. There is no "later".
- "Just animate the height." Layout properties jank on the main thread;
layoutprop or a different design. - "AutoAnimate is beneath us — rewrite the list in Motion." If add/remove/move is all the list needs, one ref beats thirty lines of variants.
- "Copy the framer-motion snippet from that 2023 blog post." Verify against current docs; the package, imports, and stagger idiom changed.
Output
Working animation code in a React codebase: components using motion/react primitives
(or deliberately simpler tiers per the Step-1 table), an app-level reduced-motion posture,
and test setup that keeps animated components deterministic. Consumers are the codebase's
reviewers and test suite — animation that ships with accessibility, performance, and
restraint already satisfied.
Related
- A UI/UX design-guidelines skill (e.g. one carrying animation duration/meaning rules) is the METHOD source for when/what to animate; this skill is the implementation counterpart.
- A component-styling skill (Radix/Tailwind) owns the
data-stateCSS tier of the Step-1 table. - A router skill (e.g. TanStack Router) owns route structure; this skill only wraps route views for transitions.
- An illustrations skill owns Lottie/animated imagery — adjacent, not this skill's surface.
- A component-testing skill owns the RTL/vitest harness this skill's testing guidance plugs into.
Progressive disclosure
references/layout-and-shared-elements.md— load when animating layout changes, shared elements (layoutId), or reordering lists.references/values-and-imperative.md— load for motion values, transforms/springs, imperative sequences, or animated number tickers.references/a11y-and-restraint.md— load when wiring reduced-motion, auditing accessibility, or defining motion tokens/restraint rules.references/integration-and-testing.md— load when combining Motion with Radix/shadcn, Tailwind, or a router, when using AutoAnimate, or when tests involve animated components.references/sources.md— research provenance; load only when auditing claims.
Body budget
description≤ 1,024 chars (agentskills.io cap).- Body ≤ ~500 lines / 5,000 tokens soft target; overflow lives in
references/.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

