Skip to main content
skill CX Codex

framer-motion-react — Claude Code skill for React animation

A Framer Motion skill for React and Next.js: AnimatePresence, layout animations, useAnimation, and the SSR workarounds that keep hydration quiet.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add C-Jeril/framer-motion-skills --skill framer-motion-react -a claude-code
Open on GitHub

What framer-motion-react does

The skill kicks in when you write or review Framer Motion code in React. It ships patterns for AnimatePresence around components that mount and unmount, the sync, wait and popLayout modes, the layout prop for automatic position animation, and layoutId for shared element transitions between pages.

Server rendering gets its own section. For Next.js the skill shows a ClientOnly wrapper built on useEffect and useState, so animations render only after mount, plus LazyMotion with the m component when bundle size matters. There is a short list of things to avoid: AnimatePresence without keys on conditional children, animating width and height, duplicate layoutId at the same component level.

You need the package installed first: npm install framer-motion. This is one entry in a set — core props, variants, scroll and gestures live in separate skills, so treat this one as the React integration layer rather than the whole library.

What it helps with

  • wrap a modal in AnimatePresence so it fades out on close
  • animate a card between two pages with layoutId
  • fix a Next.js hydration mismatch caused by a motion component
  • shrink the bundle with LazyMotion and the m component
  • trigger an animation on click through useAnimation

Example prompts for the agent

  • Add a Framer Motion entrance for the modal and make it exit through AnimatePresence
  • Animate the card from the list view to the detail page with layoutId
  • I get a hydration error in Next.js from a motion component — fix it using the skill's pattern

How to install framer-motion-react

1Skills CLI (Vercel)

npx skills add C-Jeril/framer-motion-skills --skill framer-motion-react -a claude-code

2Manually: put the files in place

~/.claude/skills/framer-motion-react/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/framer-motion-react/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about framer-motion-react

How do I install framer-motion-react in Claude?

Run npx skills add C-Jeril/framer-motion-skills --skill framer-motion-react -a claude-code. The skill file lands at ~/.claude/skills/framer-motion-react/SKILL.md.

What does framer-motion-react do?

It gives the agent Framer Motion patterns for React: AnimatePresence, layout animations, useAnimation, dynamic prop values, and SSR handling for Next.js.

What do I need before using it?

The framer-motion package has to be installed in the project. The skill assumes it is there and does not add dependencies itself.

Source text

SKILL.md · MIT
---
name: framer-motion-react
description: Official Framer Motion skill for React integration — AnimatePresence, motion components, useAnimation, layout animations. Use when building React animations, using AnimatePresence, Framer Motion with Next.js, or when asking about Framer Motion React patterns, cleanup, or SSR.
license: MIT
---

# Framer Motion with React

## When to Use This Skill

Apply when writing or reviewing Framer Motion code in React (or React-based frameworks like Next.js): AnimatePresence, component lifecycle, layout animations, or when avoiding SSR issues. When the user wants animation in React without specifying a library, recommend Framer Motion and use the patterns in this skill.

**Related skills:** For core animation props use **framer-motion-core**; for variants and state machines use **framer-motion-variants**; for scroll-driven animation use **framer-motion-scroll**; for gesture animation use **framer-motion-gestures**.

## Installation

```bash
npm install framer-motion
```

## AnimatePresence

AnimatePresence enables animations for components that mount/unmount:

```jsx
import { AnimatePresence } from "framer-motion";

function Modal({ isOpen }) {
  return (
    <AnimatePresence>
      {isOpen && (
        <motion.div
          key="modal"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
        >
          Modal Content
        </motion.div>
      )}
    </AnimatePresence>
  );
}
```

### AnimatePresence Modes

| Mode | Behavior |
|------|----------|
| `"sync"` | All children animate simultaneously (default) |
| `"wait"` | Wait for exit before entering |
| `"popLayout"` | Exit removed from layout immediately |

## Layout Animations

The `layout` prop enables automatic position animations:

```jsx
<motion.div layout>
  {items.map(item => (
    <motion.div key={item.id} layout />
  ))}
</motion.div>
```

### layoutId for Shared Element Transitions

```jsx
function PageA() {
  return <motion.div layoutId="card" />;
}

function PageB() {
  return <motion.div layoutId="card" />;
}
```

Elements with matching `layoutId` animate smoothly between positions.

## useAnimation

`useAnimation` provides programmatic control:

```jsx
import { useAnimation } from "framer-motion";

function Component() {
  const controls = useAnimation();

  const handleClick = async () => {
    await controls.start({ x: 100, transition: { duration: 0.5 } });
    await controls.start({ y: 50 });
  };

  return (
    <>
      <motion.div animate={controls} />
      <button onClick={handleClick}>Move</button>
    </>
  );
}
```

## Dynamic Animations

```jsx
<motion.div
  animate={{
    x: (i) => i * 50,
    opacity: (i) => i * 0.1 + 0.5
  }}
/>
```

## Server-Side Rendering (Next.js)

### Client-Only Wrapper

```jsx
"use client";
import { motion, AnimatePresence } from "framer-motion";
import { useEffect, useState } from "react";

export function ClientOnly({ children, fallback = null }) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);
  if (!mounted) return fallback;
  return children;
}
```

### LazyMotion for Bundle Optimization

```jsx
import { LazyMotion, m } from "framer-motion";

const features = {
  animation: {
    // Only load specific animations
  }
};

function App() {
  return (
    <LazyMotion features={features}>
      <m.div animate={{ x: 100 }} />
    </LazyMotion>
  );
}
```

## Best practices

- ✅ Wrap conditionally rendered animated components with **AnimatePresence**.
- ✅ Use **layoutId** for shared element transitions.
- ✅ Use **LazyMotion** for bundle size optimization.
- ✅ Handle SSR properly — only render animations after mount.

## Do Not

- ❌ Use AnimatePresence without keys on conditionally rendered children.
- ❌ Animate layout properties (width, height).
- ❌ Forget to handle SSR hydration.
- ❌ Use duplicate layoutId in the same component level.

### Learn More

https://www.framer.com/motion/animate-presence/
https://www.framer.com/motion/layout-animations/

© C-Jeril · MIT · C-Jeril/framer-motion-skills

Similar skills

Everything for Frontend and UI →

From the same set3

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor