TL;DR
- Pair motion prompts with the Rottoways design system pack to fix both motion and the underlying AI-slop visuals
- Eight core Framer Motion patterns cover 95% of what AI tools generate: entrance, hover, tap, stagger, exit, scroll, layout, and drag
- Each pattern maps to a specific prompt phrase — knowing the phrase gets you the exact animation you want
- AI tools default to basic fades without guidance; motion prompts apply all patterns consistently
You're vibe coding — describing what you want and letting Cursor, Claude, or Lovable generate the React code. The output is full of motion.div, variants, whileHover, and spring transitions. But what does it all mean? And more importantly, how do you prompt for the specific pattern you need?
This cheat sheet covers the most common Framer Motion patterns that AI coding tools generate. Each section shows the code your AI tool produces, explains what it does, and tells you how to prompt for it.
Bookmark this page. You'll come back to it every time you're prompting for animations.
Pattern 1: Entrance animation (fade + slide up)
This is the most common animation AI tools generate. An element fades in and slides up from below.
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: "spring", damping: 25, stiffness: 250 }}
>
Content here
</motion.div>What it does: The element starts invisible and 20px below its final position, then springs into place.
How to prompt for it: "Add an entrance animation — fade in and slide up with spring physics."
Tune it: Increase y for a more dramatic entrance. Lower damping for more bounce. Raise stiffness for a snappier feel.
Pattern 2: Hover state with lift and shadow
Cards that respond to hover with scale, lift, and shadow elevation.
<motion.div
whileHover={{
scale: 1.02,
y: -4,
boxShadow: "0 12px 32px rgba(0,0,0,0.12)",
}}
transition={{ type: "spring", damping: 20, stiffness: 300 }}
>
Card content
</motion.div>What it does: On hover, the card scales up slightly, lifts 4px, and gets a deeper shadow. Spring physics make it feel physical.
How to prompt for it: "Add a hover effect — scale up slightly, lift with y offset, and elevate the box shadow. Use spring transition."
Tune it: scale: 1.04 for buttons (more feedback). y: -2 for subtle, y: -6 for dramatic.
Pattern 3: Tap/press feedback
Button press animation that makes clicks feel physical.
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.97 }}
transition={{ type: "spring", damping: 15, stiffness: 400 }}
>
Click me
</motion.button>What it does: Button scales up on hover and compresses on click. The spring transition makes it bounce slightly.
How to prompt for it: "Add hover scale and tap press feedback to buttons using spring physics."
Pattern 4: Staggered children
List items that enter one after another with a delay between each.
const container = {
hidden: {},
visible: {
transition: { staggerChildren: 0.06 },
},
};
const item = {
hidden: { opacity: 0, y: 15 },
visible: {
opacity: 1,
y: 0,
transition: { type: "spring", damping: 25, stiffness: 250 },
},
};
<motion.ul variants={container} initial="hidden" animate="visible">
{items.map((item) => (
<motion.li key={item.id} variants={item}>
{item.name}
</motion.li>
))}
</motion.ul>What it does: The parent orchestrates timing. Each child waits 60ms after the previous one before animating in. Creates a cascading waterfall effect.
How to prompt for it: "Stagger the list items — each one should fade in and slide up with a small delay between siblings. Use Framer Motion variants."
Tune it: staggerChildren: 0.04 for fast cascade, 0.1 for dramatic reveal.
Pattern 5: Exit animations with AnimatePresence
Elements that animate out when removed from the DOM.
import { AnimatePresence, motion } from "framer-motion";
<AnimatePresence mode="wait">
{isVisible && (
<motion.div
key="panel"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ type: "spring", damping: 25, stiffness: 250 }}
>
Panel content
</motion.div>
)}
</AnimatePresence>What it does: When isVisible becomes false, the element animates out (fades and slides up) before being removed from the DOM. Without AnimatePresence, React removes it instantly.
How to prompt for it: "Wrap conditional content in AnimatePresence. Add entrance and exit animations — fade and slide. Use mode wait so exit completes before entrance."
This is the pattern AI tools miss most often. If your AI-generated app has elements that pop in and out without transitions, it's because AnimatePresence wasn't included. Always explicitly ask for exit animations.
Pattern 6: Scroll-triggered (whileInView)
Elements that animate when they scroll into the viewport.
<motion.section
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ type: "spring", damping: 25, stiffness: 200 }}
>
Section content
</motion.section>What it does: The section starts invisible. When 30% of it enters the viewport, it fades in and slides up. once: true means it only animates on first appearance, not every time you scroll past.
How to prompt for it: "Add scroll-triggered entrance animations to each section. Trigger once when 30% visible. Fade in and slide up with spring physics."
Pattern 7: Layout animations
Smooth transitions when an element's size or position changes.
<motion.div layout transition={{ type: "spring", damping: 25, stiffness: 250 }}>
{isExpanded ? <FullContent /> : <Summary />}
</motion.div>What it does: When the content changes and the div needs to resize or reposition, Framer Motion automatically animates the layout change with spring physics. No manual calculation needed.
How to prompt for it: "Add the layout prop to the container so size changes animate smoothly. Use spring transition."
Pattern 8: Gesture drag
Draggable elements with constraints and snap-back.
<motion.div
drag="x"
dragConstraints={{ left: -100, right: 100 }}
dragElastic={0.2}
whileDrag={{ scale: 1.05 }}
>
Drag me
</motion.div>What it does: The element can be dragged horizontally within a 200px range. dragElastic adds resistance at the edges. It scales up while being dragged for visual feedback.
How to prompt for it: "Make this element draggable on the x axis with constraints and elastic edges. Scale up while dragging."
Quick reference table
| Pattern | Key props | Prompt phrase |
|---|---|---|
| Entrance | `initial`, `animate` | "fade in and slide up" |
| Hover | `whileHover` | "hover with scale and lift" |
| Tap | `whileTap` | "press feedback on click" |
| Stagger | `variants`, `staggerChildren` | "stagger the children" |
| Exit | `AnimatePresence`, `exit` | "animate out when removed" |
| Scroll | `whileInView`, `viewport` | "animate when scrolled into view" |
| Layout | `layout` | "animate size/position changes" |
| Drag | `drag`, `dragConstraints` | "make it draggable" |
What your AI tool is generating under the hood
When you tell Cursor or Claude to "add animations," here's what happens. The AI picks from these patterns based on context. A card grid gets entrance + hover. A modal gets AnimatePresence. A list gets staggered children.
The problem is that without guidance, the AI makes conservative choices — usually just Pattern 1 (basic fade-in) applied everywhere. It skips exit animations, uses linear easing instead of springs, and doesn't stagger.
This is exactly the problem motion prompts solve. A motion prompt tells the AI: "For all entrance animations, use Pattern 1 with these specific spring values. For hover, use Pattern 2. Always include AnimatePresence for conditional elements. Stagger list children by 60ms."
Instead of prompting for each pattern individually, you set the rules once and the AI applies them consistently across every component. See How to Write Animation Prompts for AI Code Tools for a full guide on crafting these prompts.
Tool-specific tips
Cursor: Add your motion specification as a Cursor Rule. Every component generated in Composer or Chat automatically follows your animation patterns.
Claude: Upload the motion prompt as Project Knowledge in Claude or reference it in your CLAUDE.md for Claude Code.
Lovable: Paste the relevant prompt section directly into your Lovable chat alongside your component request.
For best practices on timing and easing values across all patterns, see UI Animation Best Practices for AI-Generated Apps.
Motion is only half the problem
Of course, smooth motion is only one piece of why so many AI-generated apps look generic. The bigger problem is the design system underneath — the colors, typography, spacing, and component shapes that Lovable, Cursor, Claude, and Bolt repeat across every project. If your site has the same gradient hero, the same pill buttons, and the same boxy card grid as every other vibe-coded landing page, no amount of animation will fix that. Our recommended design system pack is the Rottoways design system pack — you paste it into your AI tool and it replaces the default "AI slop" aesthetic with a coherent, professional visual language while keeping your copy untouched. Pair it with motion prompts and you fix both layers at once.
Stop guessing what your AI tool needs to hear. UI Motion Prompts encodes all these Framer Motion patterns into structured prompts your AI tool can follow. Every component gets coordinated animations automatically. Browse the library.
More articles
Why Every Lovable Landing Page Looks the Same
Lovable defaults produce a recognizable visual fingerprint — the same gradient hero, the same pill buttons, the same boxy card grid. Here's why, and how to break the pattern.
Best Vibecoding Tips to Improve Your AI-Generated Website
A practical checklist of vibecoding upgrades — design system, motion, copy, and layout — that turn a generic AI-generated site into something that looks like it was built by a human.