Motion (Framer Motion) React animation library. Use for drag-and-drop, scroll animations, gestures, SVG morphing, or encountering bundle size, complex transitions, spring physics errors.
Creates React animations with drag, scroll, and layout transitions using Motion library.
npx claudepluginhub secondsky/claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/accessibility-guide.mdreferences/common-patterns.mdreferences/core-concepts-deep-dive.mdreferences/motion-vs-auto-animate.mdreferences/nextjs-integration.mdreferences/performance-optimization.mdscripts/init-motion.shscripts/optimize-bundle.shtemplates/layout-transitions.tsxtemplates/motion-nextjs-client.tsxtemplates/motion-vite-basic.tsxtemplates/scroll-parallax.tsxtemplates/ui-components.tsxMotion (package: motion, formerly framer-motion) is the industry-standard React animation library used in production by thousands of applications. With 30,200+ GitHub stars and 300+ official examples, it provides a declarative API for creating sophisticated animations with minimal code.
Key Capabilities:
Production Tested: React 19, Next.js 15, Vite 6, Tailwind v4
Complex Interactions:
Scroll-Based Animations:
Layout Transitions:
Advanced Features:
Bundle Optimization:
auto-animate instead: 3.28 KB vs 34 KB)framer-motion v12.23.24 workaround - see Known Issues)bun add motion # preferred
# or: npm install motion
# or: yarn add motion
Current Version: 12.23.24 (verified 2025-11-07)
Alternative for Cloudflare Workers:
# Use framer-motion if deploying to Cloudflare Workers
bun add framer-motion
# or: npm install framer-motion
motion component: ~34 KB minified+gzippedLazyMotion + m component: ~4.6 KBuseAnimate mini: 2.3 KB (smallest React animation library)useAnimate hybrid: 17 KBmotion ComponentTransform any HTML/SVG element into an animatable component:
import { motion } from "motion/react"
// Basic animation
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
Content fades in and slides up
</motion.div>
// Gesture controls
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
>
Click me
</motion.button>
Props:
initial: Starting state (object or variant name)animate: Target state (object or variant name)exit: Unmounting state (requires AnimatePresence)transition: Timing/easing configurationwhileHover, whileTap, whileFocus: Gesture stateswhileInView: Viewport-triggered animationdrag: Enable dragging ("x", "y", or true for both)layout: Enable FLIP layout animationsNamed animation states that propagate through component tree:
const variants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
}
<motion.div variants={variants} initial="hidden" animate="visible">
Content
</motion.div>
For advanced orchestration (staggerChildren, delayChildren, dynamic variants), load references/core-concepts-deep-dive.md.
Enables animations when components unmount:
import { AnimatePresence } from "motion/react"
<AnimatePresence>
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
Modal content
</motion.div>
)}
</AnimatePresence>
Critical Rules:
key propsCommon Mistake (exit animation won't play):
// ❌ Wrong - AnimatePresence unmounts with condition
{isVisible && (
<AnimatePresence>
<motion.div>Content</motion.div>
</AnimatePresence>
)}
// ✅ Correct - AnimatePresence stays mounted
<AnimatePresence>
{isVisible && <motion.div key="unique">Content</motion.div>}
</AnimatePresence>
Automatically animate layout changes:
<motion.div layout>
{isExpanded ? <FullContent /> : <Summary />}
</motion.div>
Special props: layoutId (shared element transitions), layoutScroll (scrollable containers), layoutRoot (fixed positioning).
For advanced patterns (LayoutGroup, layoutId orchestration), load references/core-concepts-deep-dive.md.
// Viewport-triggered
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
Fades in when entering viewport
</motion.div>
// Scroll-linked (parallax)
import { useScroll, useTransform } from "motion/react"
const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -300])
<motion.div style={{ y }}>Parallax effect</motion.div>
For advanced scroll patterns (useScroll offsets, useTransform easing, parallax layers), load references/core-concepts-deep-dive.md.
<motion.div drag="x" dragConstraints={{ left: -200, right: 200 }}>
Drag me
</motion.div>
Available: whileHover, whileTap, whileFocus, whileDrag, whileInView, drag.
For advanced drag controls (momentum, elastic, event handlers), load references/core-concepts-deep-dive.md.
<motion.div
animate={{ x: 100 }}
transition={{ type: "spring", stiffness: 100, damping: 10 }}
/>
Common presets: Bouncy { stiffness: 300, damping: 10 }, Smooth { stiffness: 100, damping: 20 }.
For spring tuning (mass, visualizer, presets), load references/core-concepts-deep-dive.md.
Vite: bun add motion → import { motion } from "motion/react" (works out of the box)
Next.js App Router: Requires "use client" directive or client component wrapper
"use client"
import { motion } from "motion/react"
Tailwind: ⚠️ Remove transition-* classes (causes conflicts with Motion animations)
Cloudflare Workers: Use framer-motion v12.23.24 instead (Motion has Wrangler build issues)
For complete integration guides (Next.js patterns, SSR, framework-specific issues), load references/nextjs-integration.md.
Bundle Size: Use LazyMotion (34 KB → 4.6 KB):
import { LazyMotion, domAnimation, m } from "motion/react"
<LazyMotion features={domAnimation}>
<m.div>Only 4.6 KB!</m.div>
</LazyMotion>
Large Lists: Use virtualization (react-window, react-virtuoso) for 50+ animated items.
For complete optimization guide (hardware acceleration, memory profiling, production benchmarks), load references/performance-optimization.md.
Respect prefers-reduced-motion:
import { MotionConfig } from "motion/react"
<MotionConfig reducedMotion="user">
<App />
</MotionConfig>
Keyboard Support: Use whileFocus for keyboard-triggered animations.
<motion.button whileFocus={{ scale: 1.1 }} tabIndex={0}>
Keyboard accessible
</motion.button>
For complete accessibility guide (ARIA patterns, screen readers, AnimatePresence workaround, testing), load references/accessibility-guide.md.
Modal Dialog (AnimatePresence + backdrop):
<AnimatePresence>
{isOpen && (
<motion.dialog exit={{ opacity: 0 }}>Content</motion.dialog>
)}
</AnimatePresence>
Accordion (height animation):
<motion.div animate={{ height: isOpen ? "auto" : 0 }}>
Content
</motion.div>
For 15+ production patterns (carousel, tabs, scroll reveal, parallax, notifications), load references/common-patterns.md.
Symptom: Components disappear instantly without exit animation.
Solution: AnimatePresence must stay mounted, wrap the conditional (not be wrapped by it):
// ❌ Wrong
{isVisible && <AnimatePresence><motion.div>Content</motion.div></AnimatePresence>}
// ✅ Correct
<AnimatePresence>
{isVisible && <motion.div key="unique">Content</motion.div>}
</AnimatePresence>
Symptom: Build fails with "motion is not defined" or SSR errors.
Solution: Add "use client" directive:
"use client"
import { motion } from "motion/react"
Symptom: Animations stutter or don't work.
Solution: Remove transition-* classes (Motion overrides CSS transitions):
// ❌ Wrong: <motion.div className="transition-all" animate={{ x: 100 }} />
// ✅ Correct: <motion.div animate={{ x: 100 }} />
Symptom: Wrangler build fails when using motion package.
Solution: Use framer-motion v12.23.24 instead (GitHub issue #2918):
bun add framer-motion # Same API, works with Workers
Symptom: 50-100+ animated items cause severe slowdown.
Solution: Use virtualization (react-window, react-virtuoso).
For 5+ additional issues (layoutScroll, layoutRoot, AnimatePresence + layoutId), load references/nextjs-integration.md or references/core-concepts-deep-dive.md.
Claude should load these references based on user needs:
references/core-concepts-deep-dive.md when:references/performance-optimization.md when:references/nextjs-integration.md when:references/accessibility-guide.md when:references/common-patterns.md when:references/motion-vs-auto-animate.md when:This skill includes 5 production-ready templates in the templates/ directory:
Copy templates into your project and customize as needed.
This skill includes 4 comprehensive reference guides:
See references/ directory for detailed guides.
This skill includes 2 automation scripts:
See scripts/ directory for automation tools.
Related Skills: auto-animate (simple lists), tailwind-v4-shadcn (styling), nextjs (App Router), cloudflare-worker-base
Motion vs AutoAnimate: Load references/motion-vs-auto-animate.md for detailed comparison.
Token Savings: ~83% (30k → 5k tokens) | Error Prevention: 100% (29+ errors) | Time Savings: ~85% (2-3 hrs → 20-30 min)
| Package | Version | Status |
|---|---|---|
| motion | 12.23.24 | ✅ Latest stable |
| framer-motion | 12.23.24 | ✅ Alternative for Cloudflare |
| react | 19.2.0 | ✅ Latest stable |
| vite | 6.0.0 | ✅ Latest stable |
Found an issue or have a suggestion?
Production Tested: ✅ React 19 + Next.js 15 + Vite 6 + Tailwind v4
Token Savings: ~83%
Error Prevention: 100% (29+ documented errors prevented)
Bundle Size: 2.3 KB (mini) - 34 KB (full), optimizable to 4.6 KB with LazyMotion
Accessibility: MotionConfig reducedMotion support
Ready to use! Install with ./scripts/install-skill.sh motion
Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.