Skip to content

React Animation prompt

Rules that make your coding agent animate React the way it ships today: CSS and Tailwind CSS v4 first, Motion from motion/react for exits and layout, and React's View Transitions.

What it makes your agent good at

Agents still import framer-motion, animate width and top, put AnimatePresence inside the condition so exits never play, and forget people who ask for less motion. This prompt has them reach for CSS first, use Motion only for presence, layout, gestures and scroll, animate transform and opacity only, and use React 19.3's ViewTransition for route changes.

  1. CSS before JavaScriptTailwind CSS v4 transitions, the starting: variant and theme keyframes, and the headless libraries' own enter and exit attributes.
  2. Motion, imported rightmotion/react in Client Components, motion/react-client in Server Components, and LazyMotion with m for bundle size.
  3. Exits that playAnimatePresence kept mounted with stable keys, the right mode, and one system owning each overlay's exit.
  4. Compositor-only motionTransform and opacity only, layout animations through transforms, and motion values that never re-render React.
  5. Reduced motion respectedMotionConfig reducedMotion user, useReducedMotion, motion-safe and motion-reduce, and a pause for long motion.
  6. View TransitionsReact 19.3's ViewTransition for shared elements and route changes, with Next.js 16 transition types.

The React Animation rules

130 lines, current to Motion 12, React 19.3 and Tailwind CSS 4.3. Last reviewed October 23, 2026. Plain Markdown, no front matter: each agent's is below.

Download

react-animation.md

# React Animation

You are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.

## Before you write code

- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).
- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.
- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.
- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.

## Choose the tool

- CSS: hover, focus and press states, color, small toggles, entry of new elements, spinners, and the open and close of headless overlays. No JavaScript, and it works before hydration.
- Motion: exits of elements React unmounts, layout changes (size, position, reordering, shared elements), drag and springs that follow input, scroll-linked values and sequences.
- React `<ViewTransition>`: route changes, Suspense reveals and swapping whole regions.
- Animate only `transform` (`x`, `y`, `scale`, `rotate`), `opacity`, and sparingly `filter`: they run on the compositor at 60fps. Never animate `width`, `height`, `top`, `left` or `margin` to move things; use Motion's `layout` for size and position changes.
- UI motion is short: 150 to 300 ms for small elements, up to 500 ms for large ones, exits faster than entries. No motion on every keystroke or on page load for content people came to read.

## CSS with Tailwind CSS v4

- Transition only what changes: `transition-opacity`, `transition-colors`, `transition-transform` (in v4 it covers the `translate`, `scale` and `rotate` properties the utilities set), or `transition-[opacity,translate]`, with `duration-200 ease-out`. Avoid `transition-all`.
- Entry without JavaScript: the `starting:` variant (`@starting-style`), as in `transition-opacity starting:opacity-0`. For elements shown and hidden with `display` (`[popover]`, `<dialog>`, `hidden`), use a transition that includes `display` (v4's plain `transition` does) plus `transition-discrete`, so the exit runs before `display: none`.
- Custom keyframes are theme tokens in CSS:

```css
@theme {
  --animate-fade-up: fade-up 200ms ease-out;
  @keyframes fade-up {
    from { opacity: 0; translate: 0 8px; }
  }
}
```

- Headless overlays wait for your CSS before unmounting. Base UI: style `data-starting-style` and `data-ending-style` (`data-starting-style:opacity-0 data-ending-style:opacity-0`). Radix: `data-state="open" | "closed"`, and it waits only for keyframe animations on exit, not transitions. React Aria: `data-entering` and `data-exiting`.

## Motion

```tsx
"use client";

import { AnimatePresence, motion } from "motion/react";
import type { ReactNode } from "react";

export function Reveal({ open, children }: { open: boolean; children: ReactNode }) {
  return (
    <AnimatePresence initial={false}>
      {open && (
        <motion.div
          key="panel"
          initial={{ opacity: 0, y: -4 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: -4, transition: { duration: 0.15 } }}
          transition={{ type: "spring", visualDuration: 0.25, bounce: 0.1 }}
        >
          {children}
        </motion.div>
      )}
    </AnimatePresence>
  );
}
```

- Motion components live in Client Components. In a Server Component, `import * as motion from "motion/react-client"` for a `motion.div` with `initial` and `animate` only.
- Springs for movement (`type: "spring"` with `visualDuration` and `bounce`, or `stiffness` and `damping`); tweens (`duration`, `ease`) for opacity and color. `initial={false}` skips the first-render animation.
- Variants coordinate a tree: children inherit the parent's `initial` and `animate` labels. Stagger from the parent's `transition` (`delayChildren: stagger(0.05)`, or `staggerChildren` in older code).
- Gestures: `whileHover`, `whileTap`, `whileFocus`, `drag` with `dragConstraints`, and `whileInView` with `viewport={{ once: true, amount: 0.3 }}`. They are visual: keep the action in `onClick` on a real button or link.
- Wrap custom components with `motion.create(Component)`; the component passes `ref` (a plain prop in React 19) to its DOM node.

## Exits that actually run

- `AnimatePresence` stays mounted and the condition goes inside it. Each direct child has a stable, unique `key` (an id, never an index); changing the key exits the old element and enters the new one, which is how you animate steps and slides.
- The `exit` must be on the motion element that is the direct child, or on the root of the child component.
- `mode="wait"` finishes the exit before the entry (swapping one view for another); `mode="popLayout"` takes the exiting element out of the flow so siblings with `layout` close the gap (lists); `sync` is the default.
- For lists, key items by id, add `layout` to each item and `initial={false}` on `AnimatePresence` so the first render doesn't animate.
- With headless overlays, one system owns the exit. Prefer the CSS hooks above. To use Motion instead, control `open`, keep the content mounted in the library (`keepMounted` in Base UI, `forceMount` in Radix) and let `AnimatePresence` decide when it leaves. Never wait for an exit with `setTimeout`: use `onExitComplete`.

## Layout, scroll and sequences

- `layout` animates size and position with transforms. Use `layout="position"` on text that shouldn't stretch, and set `borderRadius` and `boxShadow` in `style` so Motion corrects them while scaling.
- `layoutId` makes a shared element (a tab indicator, a card opening into a dialog): render one element per id at a time and swap which one is mounted. `LayoutGroup` lets siblings that render separately animate together; give it an `id` when the component appears more than once. Add `layoutScroll` to scrolling containers of layout children.
- Scroll: `useScroll({ target: ref, offset: ["start end", "end start"] })` returns `scrollYProgress` (0 to 1); map it with `useTransform(scrollYProgress, [0, 1], [0, -80])`, smooth it with `useSpring`, and bind it through `style`. Motion values update without re-rendering: never mirror them into state, and use `useMotionValueEvent` for side effects.
- Sequences: `const [scope, animate] = useAnimate()`, `ref={scope}`, then `await animate("li", { opacity: 1 }, { delay: stagger(0.05) })` from an effect or a handler. Selectors are scoped, and animations stop when the component unmounts.

## Bundle size

Large trees of motion components cost bundle size. Use `LazyMotion` with `m`:

```tsx
"use client";

import { domAnimation, LazyMotion } from "motion/react";
import * as m from "motion/react-m";
import type { ReactNode } from "react";

export function MotionShell({ children }: { children: ReactNode }) {
  return <LazyMotion features={domAnimation} strict>{children}</LazyMotion>;
}
// below it: <m.div animate={{ opacity: 1 }} /> instead of motion.div
```

`domMax` adds layout and drag; `features` also takes a function returning `import("./motion-features").then((mod) => mod.default)` to load them after first paint. `strict` throws if a full `motion.*` component slips in.

## Reduced motion

- Wrap the app once in `<MotionConfig reducedMotion="user">`: when the system asks for less motion, Motion drops transform and layout animations and keeps opacity and color.
- `useReducedMotion()` for the rest: swap slides for fades, stop autoplay and parallax.
- In CSS, `motion-safe:` opts movement in and `motion-reduce:` takes it out (`motion-reduce:transition-none`, `motion-reduce:animate-none`).
- Anything that moves for more than five seconds gets a pause control. Set `aria` states to the end state at once, not when the animation ends, and never move a focused element out from under the user.

## View Transitions

- `import { ViewTransition } from "react"`. It animates only updates inside `startTransition`, `useDeferredValue`, Suspense reveals and framework navigations, never a plain `setState`.
- The same `name` on two elements morphs one into the other. `enter`, `exit`, `share`, `update` and `default` take a class (or an object keyed by transition type, set with `addTransitionType`), styled with `::view-transition-old(.slide)` and `::view-transition-new(.slide)`. Give named elements `default="none"` so they don't animate on unrelated transitions, and keep `share` explicit with it.
- Next.js 16 needs no config: tag navigations with `<Link transitionTypes={["nav-forward"]}>` or `router.push(href, { transitionTypes })`, and put enter and exit wrappers in `page.tsx`, not layouts, which never unmount.
- Add `::view-transition { pointer-events: none; }`, and zero `::view-transition-*` animation durations under `prefers-reduced-motion: reduce`. Don't run a view transition and a Motion layout animation on the same element.

## Do not

- Do not import from `framer-motion` in new code, or write `motion(Component)` (now `motion.create`), `AnimateSharedLayout` (now `layoutId` and `LayoutGroup`) or `exitBeforeEnter` (now `mode="wait"`).
- Do not put `AnimatePresence` inside the condition, key its children by index, or animate an element both with CSS classes and Motion.
- Do not add `will-change` everywhere or animate layout properties for movement.
- Do not set React state on every animation frame or scroll event.

## Before you finish

- Run the type checker.
- Record a Performance trace with 4x CPU throttling: transform and opacity animations show no layout or paint per frame.
- Emulate `prefers-reduced-motion: reduce` in the browser's rendering tools and check every animation you touched.
- Open and close each overlay fast and repeatedly: exits finish, nothing stays stuck half-visible, and focus returns where it should.

10,068 characters, 1,442 words. Under Windsurf's 12,000-character limit for a rule, as every prompt here is.

Use it in your agent

The same rules, where your agent reads them. Each file has the front matter its agent needs, set to load when the task fits.

Claude Code

A rule it loads every session

  1. Save it as .claude/rules/react-animation.md in your project, front matter included, or run the install command.
  2. Claude Code loads every file in .claude/rules with your CLAUDE.md when a session starts.
  3. Prefer one file? Paste it into CLAUDE.md under its own heading instead.

.claude/rules/react-animation.md

# React AnimationYou are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.## Before you write code- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.## Choose the tool…

Or let the shadcn CLI write this file: sign in (free) for your command.

Cursor

A project rule with front matter

  1. Save it as .cursor/rules/react-animation.mdc, front matter included, or run the install command.
  2. Cursor attaches it when you work on matching files, or when the task fits its description.
  3. Check it under Cursor Settings, Rules, then commit the folder for your team.

.cursor/rules/react-animation.mdc

---description: "Animation in React: CSS and Tailwind transitions, Motion (motion/react) presence, layout and gestures, View Transitions and reduced motion."alwaysApply: false---# React AnimationYou are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.## Before you write code- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.## Choose the tool…

Or let the shadcn CLI write this file: sign in (free) for your command.

Windsurf

A workspace rule for Cascade

  1. Save it as .windsurf/rules/react-animation.md, or run the install command.
  2. trigger: model_decision lets Cascade pull it in when the task fits its description.
  3. Windsurf reads up to 12,000 characters per rule; this one is 10,068.

.windsurf/rules/react-animation.md

---trigger: model_decisiondescription: "Animation in React: CSS and Tailwind transitions, Motion (motion/react) presence, layout and gestures, View Transitions and reduced motion."---# React AnimationYou are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.## Before you write code- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.## Choose the tool…

Or let the shadcn CLI write this file: sign in (free) for your command.

GitHub Copilot

Instructions for the repository

  1. Save it as .github/instructions/react-animation.instructions.md, or run the install command.
  2. applyTo: "**" applies it to every request in this repository.
  3. Or paste it into .github/copilot-instructions.md, which Copilot reads for every request.

.github/instructions/react-animation.instructions.md

---description: "Animation in React: CSS and Tailwind transitions, Motion (motion/react) presence, layout and gestures, View Transitions and reduced motion."applyTo: "**"---# React AnimationYou are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.## Before you write code- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.## Choose the tool…

Or let the shadcn CLI write this file: sign in (free) for your command.

Codex & AGENTS.md

The file most agents read

  1. Paste it into AGENTS.md at your project's root, under its own heading.
  2. Codex reads AGENTS.md before it starts work, and so do Cursor, Zed, Jules, Amp and Copilot's coding agent.
  3. A folder can have its own AGENTS.md: the one closest to the file being edited wins.

AGENTS.md

## React AnimationYou are working in a React 19 project with TypeScript and Tailwind CSS v4. Animate with CSS first, and with Motion (the `motion` package, imported from `motion/react`) where CSS can't do the job. Write code for the versions in `package.json`: Motion is the library once called Framer Motion, and React 19.3 ships View Transitions.### Before you write code- Check `package.json`: `motion` (v12) or an older `framer-motion`. Never install both; the API is the same, only the imports change. Check that Tailwind is v4 (theme in CSS, no `tailwind.config.js`).- Read the global stylesheet for existing `--animate-*`, duration and easing tokens, and reuse them.- Check where overlays come from (Base UI, Radix, React Aria): each exposes its own enter and exit hooks.- For route transitions in Next.js, read `node_modules/next/dist/docs/01-app/02-guides/view-transitions.md`.### Choose the tool…

AGENTS.md is shared with your own instructions, so paste the rules in: the copy sets their headings a level down.

Rules teach it. The MCP equips it. With Pro, your agent installs every component, block and icon it needs, from a prompt.

Get Pro

Pricing

Give your agent the parts, with Pro

The prompts are free. Every Pro plan adds the MCP server, so your agent installs the components, blocks and icons it writes code around.

4.9/5 out of 5 · 150+ reviewsfrom 150+ founders and developers.

Billed once a year in USD. Cancel anytime.

Individual

For personal projects & open source

$32instead of $49/mo

$389 billed yearly

  • How many people can use the license.Seats: 1 seat
  • Client work, SaaS products and anything you charge for.Commercial use: Personal & open source only
  • Page sections in 56 categories, from heroes and pricing tables to dashboards and settings, on every framework and UI library, in your theme.Blocks: All 6,181 blocks
  • Complete Next.js sites for startups, SaaS, agencies and portfolios, every page designed, ready to ship.Templates: All 14 templates
  • Your AI agent searches, previews and installs any component, block, icon or DESIGN.md from a prompt: 22 tools in Claude Code, Cursor, VS Code and 35 more clients.MCP server: 38 AI clients
  • Buttons with motion and states of their own, from an arrow that slides in to a burst of confetti.Animated buttons: All 35 buttons
  • Typewriters, scrambles, counters and more, for headlines, labels and numbers.Text effects: All 97 effects
  • Animated backgrounds for heroes, sections and cards, from a soft aurora to a flock that flees the cursor. Most are pure CSS.Backgrounds: All 100 backgrounds
  • WebGPU shaders, from a slow aurora to a black hole, each drawing only while it's on screen.Shaders: All 100 shaders
  • One design and one theme on all four: the components, blocks and effects are built for each framework.Frameworks: React, Vue, Svelte, Solid
  • React on Base UI, Radix UI, React Aria or Ark UI: install the version for the library your project already uses. Vue, Svelte and Solid run on Ark UI.UI libraries: Base UI, Radix, Aria, Ark
  • From a button to a date picker, a color picker or a guided tour: accessible, typed in TypeScript, each with live demos.Components: All 174 components
  • Real-world patterns built from the components, in 53 galleries: forms, tables, menus, dialogs and more.Examples: All 1,103 examples
  • Area, bar, line, pie, radar and radial charts on TanStack Charts, on every framework. React also gets the Recharts originals.Charts: All 70 charts
  • Debounce, local storage, media queries and more: each hook is one typed file you own.React hooks: All 35 hooks
  • From 222 libraries, Lucide, Heroicons, Tabler and Material Symbols among them, as SVG or a React component in one command.Icons: 294k+ icons
  • Stripe, Linear, Apple and 497 more: a brand's colors, typography and components in one file your AI agent builds from.DESIGN.md files: All 500 brands
  • Restyle every component and block at once: 8 styles, 7 grays, 18 colors and 5 radii, shared as a shadcn preset code.Theme builder: 8 styles × 18 colors
  • Priority requests are answered first.Support: Standard

Team

Most popular

For freelancers, agencies & startups

$66instead of $99/mo

$789 billed yearly · ≈ $13/dev/mo

Everything in Individual, plus

  • How many people can use the license.Seats: Up to 5 seats
  • Client work, SaaS products and anything you charge for.Commercial use: Included
  • Priority requests are answered first.Support: Priority

Organization

For companies with larger teams

$132instead of $199/mo

$1,589 billed yearly

Everything in Team, plus

  • How many people can use the license.Seats: Unlimited seats
  • Secure checkout via Stripe
  • Code lives in your repo
  • Keep what you've shipped if you cancel
  • License terms

React Animation prompt FAQ

What the React Animation prompt covers and how to use it in your agent.

How does the React Animation prompt respect prefers-reduced-motion?

It wraps the app in MotionConfig with reducedMotion set to user, so Motion drops transform and layout animations for people who ask for less motion while keeping fades. It uses useReducedMotion for custom cases, the motion-safe and motion-reduce variants in CSS, and zeroes view transition durations under the same media query.

Does the React Animation prompt cover React View Transitions?

Yes. It uses ViewTransition from React 19.3 for shared elements, Suspense reveals and route changes, and explains that only transitions, deferred values and Suspense reveals trigger it. It covers transitionTypes on Next.js 16's Link and router.push, keeps the page clickable during a transition and respects reduced motion.

4.9 out of 5 from 150+ developers

Rules teach it. The MCP equips it.

Every component, block and icon, installed by your AI agent on your stack. The prompts stay free.

Get Pro
  • Cancel anytime
  • Keep what you've shipped