--- name: motion-framer description: Modern animation library for React and JavaScript. Create smooth, production-ready animations with motion components, variants, gestures (hover/tap/drag), layout animations, AnimatePresence exit animations, spring physics, and scroll-based effects. Use when building interactive UI components, micro-interactions, page transitions, or complex animation sequences. --- # Motion & Framer Motion ## Overview Motion (formerly Framer Motion) is a production-ready animation library for React and JavaScript that enables declarative, performant animations with minimal code. It provides `motion` components that wrap HTML elements with animation superpowers, supports gesture recognition (hover, tap, drag, focus), and includes advanced features like layout animations, exit animations, and spring physics. **When to use this skill:** - Building interactive UI components (buttons, cards, menus) - Creating micro-interactions and hover effects - Implementing page transitions and route animations - Adding scroll-based animations and parallax effects - Animating layout changes (resizing, reordering, shared element transitions) - Drag-and-drop interfaces - Complex animation sequences and state-based animations - Replacing CSS transitions with more powerful, controllable animations **Technology:** - **Motion** (v11+) - The modern, smaller library from Framer Motion creators - **Framer Motion** - The full-featured predecessor (still widely used) - React 18+ compatible, also supports Vue - Supports TypeScript - Works with Next.js, Vite, Remix, and all modern React frameworks ## Core Concepts ### 1. Motion Components Convert any HTML/SVG element into an animatable component by prefixing with `motion.`: ```jsx import { motion } from "framer-motion" // Regular HTML becomes motion component ``` Every motion component accepts animation props like `animate`, `initial`, `transition`, and gesture props like `whileHover`, `whileTap`, etc. ### 2. Animate Prop The `animate` prop defines the target animation state. When values change, Motion automatically animates to them: ```jsx // Simple animation - x position changes // Multiple properties // Animates when state changes const [isOpen, setIsOpen] = useState(false) ``` ### 3. Initial State Set the initial state before animation using the `initial` prop: ```jsx ``` Set `initial={false}` to disable initial animations on mount. ### 4. Transitions Control how animations move between states using the `transition` prop: ```jsx // Duration-based // Spring physics // Different transitions for different properties ``` **Transition types:** - `"tween"` (default) - Duration-based with easing - `"spring"` - Physics-based spring animation - `"inertia"` - Decelerating animation (used in drag) ### 5. Variants Organize animation states using named variants for cleaner code and propagation to children: ```jsx const variants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0 }, exit: { opacity: 0, scale: 0.9 } } ``` **Variant propagation** - Children automatically inherit parent variant states: ```jsx const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.1 // Stagger child animations } } } const itemVariants = { hidden: { x: -20, opacity: 0 }, visible: { x: 0, opacity: 1 } } ``` ## Common Patterns ### 1. Hover Animations Animate on hover using `whileHover` prop: ```jsx // Simple hover effect Hover me // Multiple properties Hover card // With custom transition Button ``` **Hover with nested elements:** ```jsx Title ``` ### 2. Tap/Press Animations Animate on tap/press using `whileTap` prop: ```jsx // Scale down on tap Click me // Combined hover + tap Interactive button // With variants const buttonVariants = { rest: { scale: 1 }, hover: { scale: 1.1 }, pressed: { scale: 0.95 } } Button ``` ### 3. Drag Interactions Make elements draggable with the `drag` prop: ```jsx // Basic dragging (both axes) // Constrain to axis // Only horizontal // Only vertical // Drag constraints // Drag with parent constraints // Visual feedback while dragging ``` **Drag events:** ```jsx console.log(info.point)} onDrag={(event, info) => console.log(info.offset)} onDragEnd={(event, info) => console.log(info.velocity)} /> ``` ### 4. Exit Animations (AnimatePresence) Animate components when they're removed from the DOM using `AnimatePresence`: ```jsx import { AnimatePresence } from "framer-motion" // Basic exit animation {isVisible && ( )} ``` **Key requirements:** - Component must be direct child of `` - Must have a unique `key` prop - Use `exit` prop to define exit animation **List items with exit animations:** ```jsx {items.map(item => ( {item.name} ))} ``` **Staggered exit animations:** ```jsx const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { when: "beforeChildren", staggerChildren: 0.1 } }, exit: { opacity: 0, transition: { when: "afterChildren", staggerChildren: 0.05, staggerDirection: -1 // Reverse order } } } {show && ( )} ``` ### 5. Layout Animations Automatically animate layout changes (position, size) with the `layout` prop: ```jsx // Animate all layout changes // Animate only position changes // Animate only size changes ``` **Grid layout animation:** ```jsx const [columns, setColumns] = useState(3) {items.map(item => ( ))} ``` **Shared layout animations (layoutId):** Connect two different elements for smooth transitions using `layoutId`: ```jsx // Tab indicator example // Modal opening from thumbnail setExpanded(true)} /> {expanded && ( )} ``` ### 6. Scroll-Based Animations Animate elements when they enter the viewport using `whileInView`: ```jsx Animates when scrolled into view ``` **Viewport options:** - `once: true` - Animation triggers only once - `amount: 0.5` - Percentage of element visible (0-1) or "some" | "all" - `margin: "-100px"` - Offset viewport boundaries **Staggered scroll animations:** ```jsx ``` ### 7. Spring Animations Use spring physics for natural, bouncy animations: ```jsx // Basic spring // Customize spring physics // Visual duration (easier spring control) ``` **Spring presets:** - **Gentle**: `stiffness: 100, damping: 20` - **Wobbly**: `stiffness: 200, damping: 10` - **Stiff**: `stiffness: 400, damping: 30` - **Slow**: `stiffness: 50, damping: 20` ## Gesture Recognition Motion provides declarative gesture handlers: ### Gesture Props ```jsx ``` ### Gesture Events ```jsx {}} onHoverEnd={(event, info) => {}} onTap={(event, info) => {}} onTapStart={(event, info) => {}} onTapCancel={(event, info) => {}} onDragStart={(event, info) => {}} onDrag={(event, info) => {}} onDragEnd={(event, info) => {}} onViewportEnter={(entry) => {}} onViewportLeave={(entry) => {}} /> ``` **Event info objects contain:** - `point: { x, y }` - Page coordinates - `offset: { x, y }` - Offset from drag start - `velocity: { x, y }` - Drag velocity ## Hooks ### useAnimate Manually control animations with the `useAnimate` hook: ```jsx import { useAnimate } from "framer-motion" function Component() { const [scope, animate] = useAnimate() useEffect(() => { // Animate multiple elements animate([ [scope.current, { opacity: 1 }], ["li", { x: 0, opacity: 1 }, { delay: stagger(0.1) }], [".button", { scale: 1.2 }] ]) }, []) return (
  • Item 1
  • Item 2
) } ``` **Animation controls:** ```jsx const controls = animate(element, { x: 100 }) controls.play() controls.pause() controls.stop() controls.speed = 0.5 controls.time = 0 // Seek to start ``` ### useSpring Create spring-animated motion values: ```jsx import { useSpring } from "framer-motion" function Component() { const x = useSpring(0, { stiffness: 300, damping: 20 }) return ( ) } ``` ### useInView Detect when an element is in viewport: ```jsx import { useInView } from "framer-motion" function Component() { const ref = useRef(null) const isInView = useInView(ref, { once: true, amount: 0.5 }) return (
{isInView ? "In view!" : "Not in view"}
) } ``` ## Integration Patterns ### With GSAP Combine Motion for React state-based animations and GSAP for complex timelines: ```jsx import { motion } from "framer-motion" import gsap from "gsap" function Component() { const boxRef = useRef() const handleClick = () => { // Use GSAP for complex timeline const tl = gsap.timeline() tl.to(boxRef.current, { rotation: 360, duration: 1 }) .to(boxRef.current, { scale: 1.5, duration: 0.5 }) } return ( // Use Motion for hover/tap/layout animations ) } ``` ### With React Three Fiber Animate 3D objects using Motion values: ```jsx import { motion } from "framer-motion" import { useFrame } from "@react-three/fiber" function Box() { const x = useMotionValue(0) useFrame(() => { // Sync Motion value with Three.js position meshRef.current.position.x = x.get() }) return ( <> ) } ``` ### With Form Libraries Animate form validation states: ```jsx import { motion, AnimatePresence } from "framer-motion" function FormField({ error }) { return (
{error && ( {error} )}
) } ``` ## Performance Optimization ### 1. Use Transform Properties Transform properties (x, y, scale, rotate) are hardware-accelerated: ```jsx // ✅ Good - Hardware accelerated // ❌ Avoid - Triggers layout/paint ``` ### 2. Individual Transform Properties Motion supports individual transform properties for cleaner code: ```jsx // Individual properties (Motion feature) // Traditional (also supported) ``` ### 3. Reduce Motion for Accessibility Respect user preferences for reduced motion: ```jsx import { useReducedMotion } from "framer-motion" function Component() { const shouldReduceMotion = useReducedMotion() return ( ) } ``` ### 4. Layout Animations Performance Layout animations can be expensive. Optimize with: ```jsx // Specify what to animate // Only position, not size // Optimize transition ``` ### 5. Use layoutId Sparingly `layoutId` creates shared layout animations but tracks elements globally. Use only when needed. ## Common Pitfalls ### 1. Forgetting AnimatePresence for Exit Animations **Problem:** Exit animations don't work ```jsx // ❌ Wrong - No AnimatePresence {show && } ``` ```jsx // ✅ Correct - Wrapped in AnimatePresence {show && } ``` ### 2. Missing key Prop in Lists **Problem:** AnimatePresence can't track elements ```jsx // ❌ Wrong - No key {items.map(item => )} ``` ```jsx // ✅ Correct - Unique keys {items.map(item => ( ))} ``` ### 3. Animating Non-Transform Properties **Problem:** Janky animations, poor performance ```jsx // ❌ Avoid - Not hardware accelerated ``` ```jsx // ✅ Better - Use transforms ``` ### 4. Overusing Layout Animations **Problem:** Performance issues with many layout-animated elements ```jsx // ❌ Too many layout animations {items.map(item => {item})} ``` ```jsx // ✅ Use layout only where needed, optimize others {items.map(item => ( ))} ``` ### 5. Not Using Variants for Complex Animations **Problem:** Duplicated animation code, no child orchestration ```jsx // ❌ Repetitive ``` ```jsx // ✅ Use variants const variants = { hidden: { opacity: 0 }, visible: { opacity: 1 } } ``` ### 6. Incorrect Transition Timing **Problem:** Transitions don't apply to specific gestures ```jsx // ❌ Wrong - General transition won't apply to whileHover ``` ```jsx // ✅ Correct - Transition in whileHover or separate gesture transition ``` ## Resources ### Official Documentation - [Motion Docs](https://motion.dev/) - Official Motion documentation - [Framer Motion Docs](https://www.framer.com/motion/) - Framer Motion (legacy) - [Motion GitHub](https://github.com/framer/motion) - Source code & examples ### Bundled Resources This skill includes: **references/** - `api_reference.md` - Complete Motion API reference - `variants_patterns.md` - Variant patterns and orchestration - `gesture_guide.md` - Comprehensive gesture handling guide **scripts/** - `animation_generator.py` - Generate Motion component boilerplate - `variant_builder.py` - Interactive variant configuration tool **assets/** - `starter_motion/` - Complete Motion + Vite starter template - `examples/` - Real-world Motion component patterns ### Community Resources - [Motion Dev Discord](https://discord.gg/motion) - Official community - [Framer Motion Examples](https://www.framer.com/motion/examples/) - Interactive examples - [Motion Recipes](https://motion.dev/docs/recipes) - Common patterns - [CodeSandbox Templates](https://codesandbox.io/s/framer-motion-examples) - Live demos