# Motion

> |

- **Type:** Skill
- **Install:** `agentstack add skill-fellipeutaka-leon-motion`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [fellipeutaka](https://agentstack.voostack.com/s/fellipeutaka)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [fellipeutaka](https://github.com/fellipeutaka)
- **Source:** https://github.com/fellipeutaka/leon/tree/main/skills/motion

## Install

```sh
agentstack add skill-fellipeutaka-leon-motion
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Motion Animation Library

## Overview

Motion (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:**
- **Gestures**: drag, hover, tap, pan, focus with cross-device support
- **Scroll Animations**: viewport-triggered, scroll-linked, parallax effects
- **Layout Animations**: FLIP technique for smooth layout changes, shared element transitions
- **Spring Physics**: Natural, customizable motion with physics-based easing
- **SVG**: Path morphing, line drawing, attribute animation
- **Exit Animations**: AnimatePresence for unmounting transitions
- **Performance**: Hardware-accelerated, ScrollTimeline API, bundle optimization (2.3 KB - 34 KB)

**Production Tested**: React 19.2, Next.js 16.1, Vite 7.3, Tailwind v4

---

## When to Use This Skill

### ✅ Use Motion When:

**Complex Interactions**:
- Drag-and-drop interfaces (sortable lists, kanban boards, sliders)
- Hover states with scale/rotation/color changes
- Tap feedback with bounce/squeeze effects
- Pan gestures for mobile-friendly controls

**Scroll-Based Animations**:
- Hero sections with parallax layers
- Scroll-triggered reveals (fade in as elements enter viewport)
- Progress bars linked to scroll position
- Sticky headers with scroll-dependent transforms

**Layout Transitions**:
- Shared element transitions between routes (card → detail page)
- Expand/collapse with automatic height animation
- Grid/list view switching with smooth repositioning
- Tab navigation with animated underline

**Advanced Features**:
- SVG line drawing animations
- Path morphing between shapes
- Spring physics for natural bounce
- Orchestrated sequences (staggered reveals)
- Modal dialogs with backdrop blur

**Bundle Optimization**:
- Need 2.3 KB animation library (useAnimate mini)
- Want to reduce Motion from 34 KB to 4.6 KB (LazyMotion)

### ❌ Don't Use Motion When:

**Simple List Animations** → Use `auto-animate` skill instead:
- Todo list add/remove (auto-animate: 3.28 KB vs motion: 34 KB)
- Search results filtering
- Shopping cart items
- Notification toasts
- Basic accordions without gestures

**Static Content**:
- No user interaction or animations needed
- Server-rendered content without client interactivity

**Cloudflare Workers Deployment** → ✅ **Fixed (Dec 2024)**:
- Previous build compatibility issues resolved (GitHub issue #2918 closed as completed)
- Motion now works directly with Wrangler - no workaround needed
- Both `motion` and `framer-motion` v12.23.24 work correctly

**3D Animations** → Use dedicated 3D library:
- Three.js for WebGL
- React Three Fiber for React + Three.js

---

## Installation

### Latest Stable Version

```bash
# Using pnpm (recommended)
pnpm add motion

# Using npm
npm install motion

# Using yarn
yarn add motion
```

**Current Version**: 12.27.5 (verified 2026-01-21)

**Note for Cloudflare Workers**:
```bash
# Both packages work with Cloudflare Workers (issue #2918 fixed Dec 2024)
pnpm add motion
# OR
pnpm add framer-motion  # Same version, same API
```

### Package Information

- **Bundle Size**:
  - Full `motion` component: ~34 KB minified+gzipped
  - `LazyMotion` + `m` component: ~4.6 KB
  - `useAnimate` mini: 2.3 KB (smallest React animation library)
  - `useAnimate` hybrid: 17 KB
- **Dependencies**: React 18+ or React 19+
- **TypeScript**: Native support included (no @types package needed)

---

## Core Concepts

### 1. AnimatePresence (Exit Animations)

Enables animations when components unmount:

```tsx
import { AnimatePresence } from "motion/react"

  {isVisible && (
    
      Modal content
    
  )}

```

**Critical Rules:**
- AnimatePresence **must stay mounted** (don't wrap in conditional)
- All children **must have unique `key` props**
- AnimatePresence **wraps the conditional**, not the other way around

**Common Mistake** (exit animation won't play):
```tsx
// ❌ Wrong - AnimatePresence unmounts with condition
{isVisible && (
  
    Content
  
)}

// ✅ Correct - AnimatePresence stays mounted

  {isVisible && Content}

```

### 2. Layout Animations

**Special Props:**
- `layout`: Enable FLIP layout animations
- `layoutId`: Connect separate elements for shared transitions
- `layoutScroll`: Fix animations in scrollable containers (see Issue #5)
- `layoutRoot`: Fix animations in fixed-position elements (see Issue #7)

```tsx

  {isExpanded ?  : }

```

### 3. Scroll Animations

#### Viewport-Triggered (whileInView)
```tsx

  Fades in when 100px from entering viewport

```

#### Scroll-Linked (useScroll)
```tsx
import { useScroll, useTransform } from "motion/react"

const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -300])

  Moves up 300px as user scrolls page

```

**Performance**: Uses native ScrollTimeline API when available for hardware acceleration.

---

## Integration Guides

### Vite + React + TypeScript

```bash
pnpm add motion
```

Import: `import { motion } from "motion/react"`

**No Vite configuration needed** - works out of the box.

### Next.js App Router (Recommended Pattern)

**Key Requirement**: Motion only works in **Client Components** (not Server Components).

**Step 1: Create Client Component Wrapper**

`src/components/motion-client.tsx`:
```tsx
"use client"

// Optimized import for Next.js (reduces client JS)
import * as motion from "motion/react-client"

export { motion }
```

**Step 2: Use in Server Components**

`src/app/page.tsx`:
```tsx
import { motion } from "@/components/motion-client"

export default function Page() {
  return (
    
      This works in Server Component (wrapper is client)
    
  )
}
```

**Alternative: Direct Client Component**
```tsx
"use client"

import { motion } from "motion/react"

export function AnimatedCard() {
  return ...
}
```

**Known Issues (Next.js 15+ + React 19)**:
- React 19 fully supported as of December 2025 (see Issue #11 for one StrictMode edge case)
- Most compatibility issues resolved in Motion 12.27.5
- AnimatePresence may fail with soft navigation
- Reorder component incompatible with Next.js routing and page-level scrolling (see Issue #10)

### Next.js Pages Router

Works without modifications:

```tsx
import { motion } from "motion/react"

export default function Page() {
  return No "use client" needed
}
```

### Tailwind CSS Integration

**Best Practice**: Let each library do what it does best.

- **Tailwind**: Static and responsive styling via `className`
- **Motion**: Animations via motion props

```tsx

  Tailwind styles + Motion animations

```

**⚠️ Remove Tailwind Transitions**: Causes stuttering/conflicts.
```tsx
// ❌ Wrong - Tailwind transition conflicts with Motion

// ✅ Correct - Remove Tailwind transition

```

**Why**: Motion uses inline styles or native browser animations, both override Tailwind's CSS transitions.

### Cloudflare Workers (✅ Now Supported)

**Status**: ✅ **Fixed as of December 2024** (GitHub issue #2918 closed as completed)

**Installation**:
```bash
# Motion now works directly with Cloudflare Workers
pnpm add motion
```

**Import:**
```tsx
import { motion } from "motion/react"
```

**Historical Note**: Prior to December 2024, there was a Wrangler ESM resolution issue requiring use of `framer-motion` as a workaround. This has been resolved, and both packages now work correctly with Cloudflare Workers.

---

## Performance Optimization

### 1. Reduce Bundle Size with LazyMotion

**Problem**: Full `motion` component is ~34 KB minified+gzipped.

**Solution**: Use `LazyMotion` + `m` component for 4.6 KB:

```tsx
import { LazyMotion, domAnimation, m } from "motion/react"

function App() {
  return (
    
      {/* Use 'm' instead of 'motion' */}
      
        Only 4.6 KB!
      
    
  )
}
```

**How it works**: Loads animation features on-demand instead of bundling everything.

**Alternative (Smallest)**: `useAnimate` mini (2.3 KB):
```tsx
import { useAnimate } from "motion/react"

function Component() {
  const [scope, animate] = useAnimate()

  return Smallest possible React animation
}
```

### 2. Hardware Acceleration

**Add `willChange` for transforms:**
```tsx

```

**Also add for**: `opacity`, `backgroundColor`, `clipPath`, `filter`

**How it works**: Tells browser to optimize for animation, uses GPU compositing.

### 3. Large Lists → Use Virtualization

**Problem**: Animating 50-100+ items causes severe slowdown.

**Solutions:**
```bash
pnpm add react-window
# or
pnpm add react-virtuoso
# or
pnpm add @tanstack/react-virtual
```

**Pattern:**
```tsx
import { FixedSizeList } from 'react-window'
import { motion } from 'motion/react'

  {({ index, style }) => (
    
      Item {index}
    
  )}

```

**Why**: Only renders visible items, reduces DOM updates and memory usage.

### 4. Use `layout` Prop for FLIP Animations

Automatically animates layout changes without JavaScript calculation:

```tsx

  {isExpanded ?  : }

```

**Performance**: Hardware-accelerated via transforms, no reflow/repaint.

---

## Accessibility

### Respect `prefers-reduced-motion`

```tsx
import { MotionConfig } from "motion/react"

  

```

**Options:**
- `"user"`: Respects OS setting (recommended)
- `"always"`: Force instant transitions
- `"never"`: Ignore user preference

**Note**: ✅ Fixed in Jan 2023 (GitHub #1567) - MotionConfig now works correctly with AnimatePresence.

---

## Common Patterns

**5 Production-Ready Patterns:**
1. **Modal Dialog** - AnimatePresence with backdrop + dialog exit animations
2. **Accordion** - Animate height with `height: "auto"`
3. **Drag Carousel** - `drag="x"` with `dragConstraints`
4. **Scroll Reveal** - `whileInView` with viewport margin
5. **Parallax Hero** - `useScroll` + `useTransform` for layered effects

See `references/common-patterns.md` for full code (15+ patterns).

---

## Known Issues & Solutions

### Issue 1: AnimatePresence Exit Not Working

**Error**: Exit animations don't play, components disappear instantly
**Source**: [GitHub Issue #3078](https://github.com/motiondivision/motion/issues/3078)

**Why It Happens**: AnimatePresence wrapped in conditional or missing `key` props. Defining `exit` props on staggered children inside modals can also prevent modal from unmounting (backdrop remains visible).

**Solution**:
```tsx
// ❌ Wrong - AnimatePresence wrapped in conditional
{isVisible && (
  
    Content
  
)}

// ✅ Correct - AnimatePresence stays mounted

  {isVisible && Content}

// ❌ Wrong - Staggered children with exit prevent modal removal

  {isOpen && (
    
      
        {items.map(item => (
          
            {item.content}
          
        ))}
      
    
  )}

// ✅ Fix for modal - Remove exit from children or set duration: 0

  {item.content}

```

### Issue 2: Large List Performance

**Symptom**: 50-100+ animated items cause severe slowdown, browser freezes.

**Solution**: Use virtualization:
```bash
pnpm add react-window
```

See `references/performance-optimization.md` for full guide.

### Issue 3: Tailwind Transitions Conflict

**Symptom**: Animations stutter or don't work.

**Solution**: Remove `transition-*` classes:
```tsx
// ❌ Wrong

// ✅ Correct

```

### Issue 4: Next.js "use client" Missing

**Symptom**: Build fails with "motion is not defined" or SSR errors.

**Solution**: Add `"use client"` directive:
```tsx
"use client"

import { motion } from "motion/react"
```

See `references/nextjs-integration.md` for App Router patterns.

### Issue 5: Scrollable Container Layout Animations

**Symptom**: Incomplete transitions when removing items from scrolled containers.

**Solution**: Add `layoutScroll` prop:
```tsx

  {items.map(item => (
    
      {item.content}
    
  ))}

```

### Issue 6: Cloudflare Workers Build Errors (✅ RESOLVED)

**Status**: ✅ **Fixed in December 2024** (GitHub issue #2918 closed as completed)

**Previous Symptom**: Wrangler build failed with React import errors when using `motion` package.

**Current State**: Motion now works correctly with Cloudflare Workers. No workaround needed.

**If you encounter build issues**: Ensure you're using Motion v12.23.24 or later and Wrangler v3+.

GitHub issue: #2918 (closed as completed Dec 13, 2024)

### Issue 7: Fixed Position Layout Animations

**Symptom**: Layout animations in fixed elements have incorrect positioning.

**Solution**: Add `layoutRoot` prop:
```tsx

  Content

```

### Issue 8: layoutId + AnimatePresence Unmounting

**Symptom**: Elements with `layoutId` inside AnimatePresence fail to unmount.

**Solution**: Wrap in `LayoutGroup` or avoid mixing exit + layout animations:
```tsx
import { LayoutGroup } from "motion/react"

  
    {items.map(item => (
      
        {item.content}
      
    ))}
  

```

### Issue 9: Reduced Motion with AnimatePresence (✅ RESOLVED)

**Status**: ✅ **Fixed in January 2023** (GitHub issue #1567 closed via PR #1891)

**Previous Symptom**: MotionConfig reducedMotion setting didn't affect AnimatePresence animations.

**Current State**: MotionConfig now correctly applies reducedMotion to AnimatePresence components. The setting works as documented.

**Optional Manual Control**: If you need custom behavior beyond the built-in support:
```tsx
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches

```

GitHub issue: #1567 (closed as completed Jan 13, 2023)

### Issue 10: Reorder Component Limitations

**Error**: Reorder auto-scroll fails, doesn't work with Next.js routing
**Source**: [GitHub Issue #3469](https://github.com/motiondivision/motion/issues/3469), #2183, #2101

**Why It Happens**:
- **Page-level scrolling**: Reorder auto-scroll only works when `Reorder.Group` is inside element with `overflow: auto/scroll`, NOT when document itself is scrollable
- **Next.js routing**: Incompatible with Next.js routing system, causes random stuck states

**Prevention**:
```tsx
// ❌ Wrong - Page-level scrolling (auto-scroll fails)

  
    {/* Auto-scroll doesn't trigger at viewport edges */}
  

// ✅ Correct - Container with overflow

  
    {items.map(item => (
      
        {item.content}
      
    ))}
  

// ✅ Alternative - Use DnD Kit for complex cases
// Motion docs officially recommend DnD Kit for:
// - Multi-row reordering
// - Dragging between columns
// - Page-level scrollable containers
// - Complex drag-and-drop interactions

// Install: pnpm add @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
```

See `references/nextjs-integration.md` for full Next.js troubleshooting guide.

### Issue 11: React 19 StrictMode Drag Bug

**Error**: Drag gestures break when dragging from top to bottom in file trees
**Source**: [GitHub Issue #3169](https://github.com/motiondivision/motion/issues/3169)

**Why It Happens**: Only occurs with React 19 + StrictMode enabled + Ant Design components. Dragged element position breaks and appears offset. Does NOT occur in React 18 or React 19 without StrictMode. Only affects top-to-bottom drag (bottom-to-top works fine).

**Prevention**: Temporarily disable StrictMode for React 19 projects using drag gestures, or use React 18 if StrictMode is critical. Awaiting official fix from Motion team.

### Issue 12: Layout Animations in Scaled Containers

**Error**: Layout animations start from incorrect positions in scaled parent containers
**Source**: [GitHub Issue #3356](https://github.com/motiondivision/motion/issues/3356)

**Why It Happens**: Layout animation system uses scaled coordinates as if they were unscaled. Motion's layout animations work in pixels, while parent scale affects visual coordinates. The mismatch causes position calculation errors.

**Prevention (Community Workaround)**:
```tsx
// Use transformTemplate to correct for parent scale
const scale = 2; // Parent's transform scale value

   {
      const match = /translate3d\((.+)px,\s?(.+)px,\s?(.+)px\)/.exec(generated);
      if (match) {
        const [,

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [fellipeutaka](https://github.com/fellipeutaka)
- **Source:** [fellipeutaka/leon](https://github.com/fellipeutaka/leon)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-fellipeutaka-leon-motion
- Seller: https://agentstack.voostack.com/s/fellipeutaka
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
