>
framer-motion
Animate React components with Framer Motion. Use when adding page transitions, gesture animations, layout animations, scroll-triggered effects, or building interactive UI with spring physics.
#framer-motion#animation#react#transitions#gestures
terminal-skillsv1.0.0
Works with:claude-codeopenai-codexgemini-clicursor
Usage
$
✓ Installed framer-motion v1.0.0
Getting Started
- Install the skill using the command above
- Open your AI coding agent (Claude Code, Codex, Gemini CLI, or Cursor)
- Reference the skill in your prompt
- The AI will use the skill's capabilities automatically
Example Prompts
- "Review the open pull requests and summarize what needs attention"
- "Generate a changelog from the last 20 commits on the main branch"
Documentation
Overview
Framer Motion is the production animation library for React. Declarative animations via props, spring physics, layout animations, gestures (drag, hover, tap), scroll-triggered effects, and shared layout transitions. Used by Vercel, Linear, Raycast.
Instructions
Step 1: Basic Animations
tsx
import { motion } from 'framer-motion'
// Animate on mount
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: 'easeOut' }}
>
<h1>Hello</h1>
</motion.div>
// Animate on hover and tap
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{ type: 'spring', stiffness: 400, damping: 17 }}
>
Click me
</motion.button>
// Exit animations (requires AnimatePresence)
import { AnimatePresence } from 'framer-motion'
<AnimatePresence>
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
/>
)}
</AnimatePresence>
Step 2: Layout Animations
tsx
// Automatic layout animation — element smoothly moves when layout changes
<motion.div layout>
{items.map(item => (
<motion.div key={item.id} layout>
{item.title}
</motion.div>
))}
</motion.div>
// Shared layout animation — element transitions between two positions
<motion.div layoutId={`card-${id}`}>
{isExpanded ? <ExpandedCard /> : <CompactCard />}
</motion.div>
Step 3: Scroll Animations
tsx
import { motion, useScroll, useTransform } from 'framer-motion'
function ParallaxHero() {
const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -200])
const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0])
return (
<motion.div style={{ y, opacity }}>
<h1>Scroll to reveal</h1>
</motion.div>
)
}
// Animate when element enters viewport
function FadeInOnScroll({ children }) {
return (
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.6 }}
>
{children}
</motion.div>
)
}
Step 4: Staggered Children
tsx
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: { staggerChildren: 0.1 },
},
}
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
}
<motion.ul variants={container} initial="hidden" animate="show">
{items.map(i => (
<motion.li key={i.id} variants={item}>{i.name}</motion.li>
))}
</motion.ul>
Guidelines
- Use
type: 'spring'for natural-feeling animations — avoid linear easing. layoutIdcreates shared element transitions (like iOS hero animations).AnimatePresenceis required for exit animations — wrap conditional renders.whileInViewwithviewport: { once: true }for scroll-triggered animations.- Framer Motion adds ~30KB to bundle. For simple animations, consider CSS transitions.
Information
- Version
- 1.0.0
- Author
- terminal-skills
- Category
- Development
- License
- Apache-2.0