---
name: animation-designer
description: Use when the user explicitly requests animations, transitions, or motion design for a web UI.
---
# Animation Designer Skill
I help you create smooth, professional animations for web applications using Framer Motion and CSS.
## Animation Gate (Required)
- **Do not add animation unless the user explicitly asks for it.**
- If the project requires `motion/react`, use it instead of `framer-motion`.
- If `ui-style-compliance` applies, follow its rules (transform/opacity only, <=200ms feedback, respect reduced motion).
## What I Do
**UI Animations:**
- Page transitions
- Component enter/exit animations
- Hover effects, button interactions
- Loading animations
**Scroll Animations:**
- Parallax effects
- Scroll-triggered animations
- Progress indicators
**Micro-interactions:**
- Button press feedback
- Form field focus states
- Success/error animations
- Drag and drop feedback
## Framer Motion Basics
### Installation
```bash
npm install framer-motion
```
### Basic Animation
```typescript
import { motion } from 'framer-motion'
export function FadeIn({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
```
---
## Common Animation Patterns
### Pattern 1: Fade In on Mount
```typescript
import { motion } from 'framer-motion'
export function Card({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
```
---
### Pattern 2: Staggered List Animation
```typescript
import { motion } from 'framer-motion'
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1
}
}
}
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 }
}
export function List({ items }: { items: string[] }) {
return (
{items.map((text, i) => (
{text}
))}
)
}
```
---
### Pattern 3: Button Hover Animation
```typescript
import { motion } from 'framer-motion'
export function AnimatedButton({ children, onClick }: {
children: React.ReactNode
onClick: () => void
}) {
return (
{children}
)
}
```
---
### Pattern 4: Modal / Dialog Animation
```typescript
import { motion, AnimatePresence } from 'framer-motion'
export function Modal({ isOpen, onClose, children }: {
isOpen: boolean
onClose: () => void
children: React.ReactNode
}) {
return (
{isOpen && (
<>
{/* Backdrop */}
{/* Modal */}
{children}
>
)}
)
}
```
---
### Pattern 5: Page Transition
```typescript
'use client'
import { motion } from 'framer-motion'
import { usePathname } from 'next/navigation'
export function PageTransition({ children }: { children: React.ReactNode }) {
const pathname = usePathname()
return (
{children}
)
}
// Usage in layout
export default function Layout({ children }) {
return (
{children}
)
}
```
---
## Scroll Animations
### Scroll-Triggered Animation
```typescript
import { motion, useScroll, useTransform } from 'framer-motion'
import { useRef } from 'react'
export function ScrollReveal({ children }: { children: React.ReactNode }) {
const ref = useRef(null)
const { scrollYProgress } = useScroll({
target: ref,
offset: ['start end', 'end start']
})
const opacity = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [0, 1, 1, 0])
const y = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [100, 0, 0, -100])
return (
{children}
)
}
```
### Parallax Effect
```typescript
import { motion, useScroll, useTransform } from 'framer-motion'
export function ParallaxSection() {
const { scrollY } = useScroll()
const y = useTransform(scrollY, [0, 500], [0, 150])
return (
Parallax Effect
)
}
```
### Scroll Progress Indicator
```typescript
import { motion, useScroll } from 'framer-motion'
export function ScrollProgress() {
const { scrollYProgress } = useScroll()
return (
)
}
```
---
## Loading Animations
### Spinner
```typescript
import { motion } from 'framer-motion'
export function Spinner() {
return (
)
}
```
### Skeleton Loader
```typescript
import { motion } from 'framer-motion'
export function SkeletonLoader() {
return (
)
}
```
### Pulsing Dots
```typescript
import { motion } from 'framer-motion'
const dotVariants = {
start: { scale: 0.8, opacity: 0.5 },
end: { scale: 1.2, opacity: 1 }
}
export function PulsingDots() {
return (
{[0, 1, 2].map((i) => (
))}
)
}
```
---
## CSS Animations
### Keyframe Animations
```css
/* Fade in animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out;
}
/* Slide in from right */
@keyframes slideInRight {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
.slide-in-right {
animation: slideInRight 0.3s ease-out;
}
/* Bounce */
@keyframes bounce {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
.bounce {
animation: bounce 0.5s ease-in-out infinite;
}
```
### Tailwind Animations
```typescript
// tailwind.config.js
module.exports = {
theme: {
extend: {
keyframes: {
'fade-in': {
'0%': { opacity: '0', transform: 'translateY(10px)' },
'100%': { opacity: '1', transform: 'translateY(0)' }
},
'slide-in': {
'0%': { transform: 'translateX(-100%)' },
'100%': { transform: 'translateX(0)' }
}
},
animation: {
'fade-in': 'fade-in 0.5s ease-out',
'slide-in': 'slide-in 0.3s ease-out'
}
}
}
}
```
**Usage:**
```typescript
Fades in
Slides in
```
---
## Micro-Interactions
### Success Checkmark Animation
```typescript
import { motion } from 'framer-motion'
export function SuccessCheckmark() {
return (
)
}
```
### Notification Badge
```typescript
import { motion } from 'framer-motion'
export function NotificationBadge({ count }: { count: number }) {
return (
{count > 0 && (
{count}
)}
)
}
```
---
## Animation Best Practices
### 1. Performance
```typescript
// ✅ Good: Animate transform and opacity (GPU accelerated)
// ❌ Bad: Animate width, height (triggers layout)
```
### 2. Duration
```typescript
// Too fast: < 100ms (feels abrupt)
// Too slow: > 500ms (feels sluggish)
// ✅ Sweet spot: 200-400ms for most UI animations
```
### 3. Easing
```typescript
// Natural motion: easeOut (starts fast, ends slow)
// Bouncy: spring
```
### 4. Reduce Motion (Accessibility)
```typescript
import { useReducedMotion } from 'framer-motion'
export function AccessibleAnimation({ children }: { children: React.ReactNode }) {
const shouldReduceMotion = useReducedMotion()
return (
{children}
)
}
```
---
## Complex Animations
### Drag and Drop
```typescript
import { motion } from 'framer-motion'
import { useState } from 'react'
export function Draggable() {
const [position, setPosition] = useState({ x: 0, y: 0 })
return (
{
setPosition({ x: info.point.x, y: info.point.y })
}}
className="w-24 h-24 bg-blue-600 rounded-lg cursor-grab active:cursor-grabbing"
/>
)
}
```
### Animated Number Counter
```typescript
import { motion, useSpring, useTransform } from 'framer-motion'
import { useEffect } from 'react'
export function AnimatedNumber({ value }: { value: number }) {
const spring = useSpring(0, { stiffness: 100, damping: 30 })
const display = useTransform(spring, (current) =>
Math.round(current).toLocaleString()
)
useEffect(() => {
spring.set(value)
}, [spring, value])
return {display}
}
// Usage
```
---
## When to Use Me
**Perfect for:**
- Creating polished UI animations
- Building interactive components
- Adding scroll effects
- Designing loading states
- Improving user feedback
**I'll help you:**
- Choose the right animation type
- Implement smooth transitions
- Optimize animation performance
- Ensure accessibility
- Create delightful micro-interactions
## What I'll Create
```
✨ Page Transitions
🎯 Micro-Interactions
📜 Scroll Animations
⏳ Loading States
🎨 Hover Effects
🎪 Complex Animations
```
Let's make your interfaces feel alive!