Tips & Tricks (Updated: 6/2/2026)

Claude Code and Framer Motion: Practical Motion for React Guide

Use Claude Code with Framer Motion/Motion for React: prompts, runnable TSX examples, pitfalls, accessibility, and verification.

Claude Code and Framer Motion: Practical Motion for React Guide

Many developers still search for Framer Motion, but the current official React docs describe the library as Motion for React. For new work, install motion and import React APIs from motion/react. If you are maintaining an older app that already standardizes on framer-motion, do not mix imports casually. For a fresh implementation or article update, use the official Motion for React documentation as the source of truth.

Claude Code can make animation work faster, but it does not remove the need for product judgment. If the prompt only says “make this feel smooth”, the generated diff may add busy transitions, miss reduced-motion preferences, or break exit animations by unmounting the wrong part of the tree. Masa tested this pattern on an internal dashboard: the first pass looked impressive, but cards bounced too far, notifications disappeared without an exit animation, and a parallax header felt heavy on a low-end laptop.

This guide treats Claude Code as a collaborator for constrained implementation. You will define intent, scope, accessibility requirements, and verification steps before asking it to change code. The examples below are copy-pasteable TSX components for a React project after npm install motion.

Start With Design Constraints

Animation should explain state change. It should not be a visual tax every time the user opens a screen. Before handing a component to Claude Code, write down the boundaries.

DecisionWhat to tell Claude CodeWhat to review
PurposeWhich state change needs helpThe animation supports comprehension
ScopeFiles it may edit and files it must not touchNo unrelated refactor appears
APIUse motion/react, support Reduced MotionImports and behavior match the docs
VerificationManual interactions and device checksThe diff was tested like a real UI

The useful mental model is simple:

Intent and constraints
  -> Claude Code prompt
  -> Motion for React implementation
  -> Manual and accessibility verification
  -> Focused follow-up prompt

A practical first prompt looks like this:

Add Motion for React animation to this existing React component.
Requirements:
- Import new Motion APIs from `motion/react`
- Do not change data fetching, form submission, or routing logic
- Respect Reduced Motion preferences
- Prefer opacity and transform animations
- Avoid layout shift
- Return a short manual test checklist with the diff

This gives Claude Code enough shape to produce a reviewable change. The import line matters because many older examples still use framer-motion; mixing both styles inside one file makes later maintenance harder.

Use Case 1: Animated Card Lists

Dashboards, article grids, and feature lists benefit from a quiet stagger. The goal is not to make every card perform. The goal is to show order and make the first scan easier. In Masa’s test, a stagger between 0.06 and 0.09 seconds felt useful for six cards; anything longer delayed interaction.

import { motion, useReducedMotion } from "motion/react";

type Feature = {
  id: string;
  title: string;
  body: string;
  metric: string;
};

const demoFeatures: Feature[] = [
  {
    id: "review",
    title: "Review queue",
    body: "Human review for Claude Code generated changes.",
    metric: "8 items",
  },
  {
    id: "motion",
    title: "Motion cleanup",
    body: "Short transitions clarify screen changes without slowing work.",
    metric: "14%",
  },
  {
    id: "a11y",
    title: "Reduced Motion",
    body: "Large movement becomes a calmer fade for users who prefer it.",
    metric: "Ready",
  },
];

export function AnimatedFeatureCards({
  items = demoFeatures,
}: {
  items?: Feature[];
}) {
  const shouldReduceMotion = useReducedMotion();

  const container = {
    hidden: { opacity: 0 },
    visible: {
      opacity: 1,
      transition: {
        staggerChildren: shouldReduceMotion ? 0 : 0.08,
      },
    },
  };

  const card = {
    hidden: {
      opacity: 0,
      y: shouldReduceMotion ? 0 : 16,
    },
    visible: {
      opacity: 1,
      y: 0,
      transition: {
        duration: 0.32,
        ease: "easeOut",
      },
    },
  };

  return (
    <motion.section
      aria-label="Feature cards"
      variants={container}
      initial="hidden"
      animate="visible"
      style={{
        display: "grid",
        gap: 16,
        gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
      }}
    >
      {items.map((item) => (
        <motion.article
          key={item.id}
          variants={card}
          whileHover={shouldReduceMotion ? undefined : { y: -4 }}
          style={{
            border: "1px solid #d9e2ec",
            borderRadius: 12,
            padding: 20,
            background: "#ffffff",
            boxShadow: "0 8px 24px rgba(15, 23, 42, 0.08)",
          }}
        >
          <p style={{ margin: 0, color: "#2563eb", fontWeight: 700 }}>
            {item.metric}
          </p>
          <h3 style={{ margin: "8px 0", fontSize: 18 }}>{item.title}</h3>
          <p style={{ margin: 0, lineHeight: 1.7, color: "#475569" }}>
            {item.body}
          </p>
        </motion.article>
      ))}
    </motion.section>
  );
}

Review this for stable keys, transform-based movement, and reduced-motion behavior. A good follow-up prompt is: “Keep the stagger, but make the list usable immediately when 12 cards are present.”

Use Case 2: Notifications With Exit Animations

AnimatePresence lets components animate when they leave the React tree. The official AnimatePresence docs emphasize that direct children need stable keys. The common failure is wrapping the whole notification area in a conditional so the parent disappears before child exits can run.

Keep the container mounted and animate individual items.

import { useState } from "react";
import { AnimatePresence, motion } from "motion/react";

type Toast = {
  id: number;
  message: string;
};

let nextToastId = 1;

export function AnimatedNotifications() {
  const [toasts, setToasts] = useState<Toast[]>([
    { id: 0, message: "Saved successfully" },
  ]);

  function addToast() {
    const id = nextToastId++;
    setToasts((current) => [
      ...current,
      { id, message: `Background job ${id} finished` },
    ]);
  }

  function dismissToast(id: number) {
    setToasts((current) => current.filter((toast) => toast.id !== id));
  }

  return (
    <div>
      <button type="button" onClick={addToast}>
        Add notification
      </button>

      <div
        aria-live="polite"
        style={{
          position: "fixed",
          right: 24,
          top: 24,
          display: "grid",
          gap: 12,
          width: "min(360px, calc(100vw - 48px))",
        }}
      >
        <AnimatePresence initial={false} mode="popLayout">
          {toasts.map((toast) => (
            <motion.div
              layout
              key={toast.id}
              initial={{ opacity: 0, x: 40, scale: 0.96 }}
              animate={{ opacity: 1, x: 0, scale: 1 }}
              exit={{ opacity: 0, x: 40, scale: 0.96 }}
              transition={{ duration: 0.2, ease: "easeOut" }}
              style={{
                borderRadius: 10,
                border: "1px solid #cbd5e1",
                background: "#ffffff",
                padding: 16,
                boxShadow: "0 12px 30px rgba(15, 23, 42, 0.16)",
              }}
            >
              <p style={{ margin: "0 0 12px", color: "#0f172a" }}>
                {toast.message}
              </p>
              <button type="button" onClick={() => dismissToast(toast.id)}>
                Dismiss
              </button>
            </motion.div>
          ))}
        </AnimatePresence>
      </div>
    </div>
  );
}

Ask Claude Code to check three things after this change: the empty state keeps the container stable, keyboard users can dismiss a notification, and aria-live does not announce too much. Animation quality is not enough if the component is noisy or hard to operate.

Use Case 3: Scroll Progress for Long Content

Landing pages and long guides often need a sense of progress. Motion’s useScroll returns motion values for page or element scroll progress. Pairing it with useSpring avoids a jittery bar.

Avoid turning every section into a parallax scene. If Reduced Motion is enabled, remove large movement and keep the content readable.

import { useRef } from "react";
import {
  motion,
  useReducedMotion,
  useScroll,
  useSpring,
  useTransform,
} from "motion/react";

const sections = [
  {
    title: "Freeze the requirement",
    body: "Before Claude Code edits anything, define purpose, target files, and forbidden changes.",
  },
  {
    title: "Move less",
    body: "Start with opacity and transform so the motion supports comprehension.",
  },
  {
    title: "Verify on real paths",
    body: "Check a slower device, keyboard navigation, and Reduced Motion before publishing.",
  },
];

export function ScrollReadingProgress() {
  const articleRef = useRef<HTMLElement | null>(null);
  const shouldReduceMotion = useReducedMotion();
  const { scrollYProgress } = useScroll({
    target: articleRef,
    offset: ["start start", "end end"],
  });

  const scaleX = useSpring(scrollYProgress, {
    stiffness: 120,
    damping: 28,
    mass: 0.2,
  });
  const y = useTransform(scrollYProgress, [0, 1], [0, -48]);

  return (
    <article ref={articleRef} style={{ position: "relative", padding: 24 }}>
      <motion.div
        aria-hidden="true"
        style={{
          position: "sticky",
          top: 0,
          zIndex: 10,
          height: 4,
          scaleX: shouldReduceMotion ? 1 : scaleX,
          transformOrigin: "0% 50%",
          background: "#2563eb",
        }}
      />

      <motion.header
        style={{
          y: shouldReduceMotion ? 0 : y,
          padding: "56px 0 32px",
        }}
      >
        <p style={{ color: "#2563eb", fontWeight: 700 }}>
          Claude Code x Motion
        </p>
        <h2 style={{ fontSize: 36, margin: 0 }}>
          A page that reveals context while you read
        </h2>
      </motion.header>

      <div style={{ display: "grid", gap: 24 }}>
        {sections.map((section) => (
          <section
            key={section.title}
            style={{
              border: "1px solid #dbe4ee",
              borderRadius: 12,
              padding: 24,
              background: "#ffffff",
            }}
          >
            <h3>{section.title}</h3>
            <p style={{ lineHeight: 1.8 }}>{section.body}</p>
          </section>
        ))}
      </div>
    </article>
  );
}

Use this for documentation, onboarding, and report pages where the reader benefits from orientation. Do not use it as filler. A progress bar that helps is better than five scroll-triggered reveals that slow the page down.

Use Case 4: Make Claude Code Review the Diff

The highest leverage prompt often comes after the implementation. Ask Claude Code to review its own diff with specific failure modes.

Review the current diff as a Motion for React implementation.
Be strict about these points:
- No accidental mix of `motion/react` and old `framer-motion` imports
- Direct children of `AnimatePresence` have stable keys
- Reduced Motion disables large movement, parallax, and autoplay-like behavior
- The code avoids frequent width, height, top, and left animation
- Manual test steps reflect real user actions

This turns the tool from a code generator into a reviewer. Because Claude Code can inspect the surrounding files, it can also catch CSS conflicts, state changes, and missing tests that a standalone snippet would hide.

Common Pitfalls

The first pitfall is stale imports. Many tutorials still show framer-motion. That can be correct in a legacy project, but new code should follow the current motion package and motion/react imports unless the repository deliberately chooses otherwise.

The second pitfall is debugging exit as if it were an easing problem. Most broken exit animations are React tree problems: the parent unmounts too early, the key is an array index, or the item never leaves through AnimatePresence.

The third pitfall is overusing layout. It is excellent for reorder and size changes, but images without dimensions, late-loading fonts, and abrupt grid changes can still make cards jump. Ask Claude Code to stabilize layout constraints, not only animation props.

The fourth pitfall is treating accessibility as a final pass. Motion’s accessibility guide explains Reduced Motion support. If your design uses large movement, parallax, or autoplay-like effects, build the calmer path first.

The fifth pitfall is testing only on a fast development machine. opacity and transform are usually safe, but huge blur, frequent shadow animation, and multiple large images can still feel heavy. Scroll the real page and record what stutters.

Publish Checklist

  • Official Motion docs and imports agree
  • Every animation has a product purpose
  • Reduced Motion removes large movement
  • AnimatePresence children have stable key values
  • Keyboard operation and focus states still work
  • Scroll effects do not reduce readability
  • The pull request or article includes verification notes

For related UI foundations, read Radix UI with Claude Code, shadcn/ui with Claude Code, and the broader Claude Code animation implementation guide. For the coding agent itself, keep Anthropic’s Claude Code documentation open.

Conclusion

The value of combining Claude Code with Framer Motion is not speed alone. The value is getting animation, accessibility, and review criteria into the same workflow before the UI ships.

Masa’s hands-on result was clear: adding motion/react, Reduced Motion, and manual verification requirements to the first prompt reduced rework more than any later polish pass. For a repeatable prompt template, use the free cheat sheet. For team adoption or multi-screen UI review, the training and consultation page is the practical next step.

#Claude Code #Framer Motion #Motion for React #React #animation #UI/UX
Free

Free PDF: Claude Code Cheatsheet

Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.

We handle your data with care and never send spam.

Level up your Claude Code workflow

Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.

Masa

About the Author

Masa

Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.