- name
- lottiefiles-motion-design-skill
- description
- Universal motion design principles for AI agents — timing, easing, choreography, and Disney animation principles adapted for UI
- triggers
- ["add animation to this component","create a loading state animation","animate this button interaction","make this transition feel more natural","choreograph these elements entering","review my animation for motion design principles","what easing should I use for this","help me with micro-interactions"]
# LottieFiles Motion Design Skill
> Skill by [ara.so](https://ara.so) — Design Skills collection.
This skill teaches AI agents to think like motion directors — choosing the right timing, easing, choreography, and emotional intent before writing animation code. Philosophy-first, implementation-agnostic approach that works with any animation system (CSS, Framer Motion, GSAP, Lottie, React Spring, etc.).
## Installation
```bash
npx skills add LottieFiles/motion-design-skill
```
The skill integrates with 40+ AI coding agents including Claude Code, Cursor, Codex, and GitHub Copilot.
## Core Philosophy
### The Three Pillars
Every animation decision flows from three questions:
1. **WHY** — What's the purpose? (feedback, guidance, delight, hierarchy)
2. **WHAT** — Which properties communicate that? (position, scale, opacity, color)
3. **HOW** — What personality matches the brand? (snappy, smooth, bouncy, minimal)
### The 8-Step Motion Checklist
Before writing any animation code:
1. **Purpose** — Why does this need to animate?
2. **Emotion** — What should the user feel?
3. **Personality** — Which motion archetype fits the brand?
4. **Properties** — Which CSS/transform properties to animate?
5. **Duration** — How long should it take?
6. **Easing** — What curve shape matches the intent?
7. **Choreography** — If multiple elements, what's the sequence?
8. **Quality** — Does it pass the motion design checklist?
## Motion Personality Archetypes
Choose one archetype per brand/project:
### 1. Snappy (Productivity, Tools)
```javascript
// Framer Motion example
const snappy = {
duration: 0.2,
ease: [0.4, 0, 0.2, 1] // easeInOutCubic
};
// CSS example
.snappy-button {
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
```
### 2. Smooth (Finance, Professional)
```javascript
// Framer Motion
const smooth = {
duration: 0.4,
ease: [0.25, 0.1, 0.25, 1] // easeInOutQuart
};
// CSS
.smooth-card {
transition: all 400ms cubic-bezier(0.25, 0.1, 0.25, 1);
}
```
### 3. Bouncy (Social, Playful)
```javascript
// Framer Motion
const bouncy = {
type: "spring",
damping: 15,
stiffness: 300
};
// CSS (approximated)
.bouncy-modal {
transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
```
### 4. Minimal (Editorial, Luxury)
```javascript
// Framer Motion
const minimal = {
duration: 0.6,
ease: [0.25, 0, 0.1, 1] // easeOutQuart
};
// CSS
.minimal-fade {
transition: opacity 600ms cubic-bezier(0.25, 0, 0.1, 1);
}
```
## Duration & Easing Reference
### Duration by Element Size
| Element Type | Duration | Use Case |
|-------------|----------|----------|
| Icon/Badge | 150-200ms | Small UI feedback |
| Button/Input | 200-300ms | Interactive elements |
| Card/Panel | 300-400ms | Medium containers |
| Modal/Drawer | 400-500ms | Large overlays |
| Page Transition | 500-700ms | Full screen changes |
### Easing by Intent
| Intent | Easing Function | Cubic Bezier | Use Case |
|--------|----------------|--------------|----------|
| **Enter** | easeOut | `(0, 0, 0.2, 1)` | Elements appearing |
| **Exit** | easeIn | `(0.4, 0, 1, 1)` | Elements disappearing |
| **Move** | easeInOut | `(0.4, 0, 0.2, 1)` | Position/size changes |
| **Attention** | easeOutBack | `(0.34, 1.56, 0.64, 1)` | Success feedback |
| **Smooth** | easeInOutQuart | `(0.25, 0.1, 0.25, 1)` | Professional feel |
## Property Selection Guide
**What each property communicates:**
- **Opacity** — Existence (appearing/disappearing)
- **Scale** — Importance (growing/shrinking attention)
- **Position (x/y)** — Origin/direction (where it came from)
- **Rotation** — Playfulness/dynamism
- **Color** — State change (success/error/focus)
**Recommended combinations:**
```javascript
// Entrance (appearing)
opacity: 0 → 1 + translateY(20px → 0)
// Exit (disappearing)
opacity: 1 → 0 + scale(1 → 0.95)
// Success feedback
scale(1 → 1.1 → 1) + color(blue → green)
// Error shake
translateX(0 → -10 → 10 → 0) with easeOutBounce
```
## Common Patterns
### Pattern 1: Button Hover/Press
```javascript
// Framer Motion
const buttonVariants = {
idle: { scale: 1 },
hover: { scale: 1.05, transition: { duration: 0.2 } },
press: { scale: 0.95, transition: { duration: 0.1 } }
};
<motion.button
variants={buttonVariants}
initial="idle"
whileHover="hover"
whileTap="press"
>
Click me
</motion.button>
```
```css
/* CSS version */
.button {
transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.button:hover {
transform: scale(1.05);
}
.button:active {
transform: scale(0.95);
transition-duration: 100ms;
}
```
### Pattern 2: Card Entrance
```javascript
// Framer Motion
const cardVariants = {
hidden: {
opacity: 0,
y: 20
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.4,
ease: [0, 0, 0.2, 1] // easeOut
}
}
};
<motion.div
variants={cardVariants}
initial="hidden"
animate="visible"
>
Card content
</motion.div>
```
```css
/* CSS version with Intersection Observer */
.card {
opacity: 0;
transform: translateY(20px);
transition: opacity 400ms ease-out,
transform 400ms ease-out;
}
.card.visible {
opacity: 1;
transform: translateY(0);
}
```
### Pattern 3: Loading → Success → Error States
```javascript
// Framer Motion
const buttonStates = {
idle: {
scale: 1,
backgroundColor: "#3b82f6"
},
loading: {
scale: 0.95,
backgroundColor: "#6366f1",
transition: { duration: 0.2 }
},
success: {
scale: [1, 1.1, 1],
backgroundColor: "#10b981",
transition: {
scale: { duration: 0.4, times: [0, 0.5, 1] },
backgroundColor: { duration: 0.3 }
}
},
error: {
x: [0, -10, 10, -10, 10, 0],
backgroundColor: "#ef4444",
transition: {
x: { duration: 0.5 },
backgroundColor: { duration: 0.3 }
}
}
};
function SubmitButton() {
const [state, setState] = useState('idle');
return (
<motion.button
variants={buttonStates}
animate={state}
>
{state === 'loading' && 'Submitting...'}
{state === 'success' && '✓ Success'}
{state === 'error' && '✗ Error'}
{state === 'idle' && 'Submit'}
</motion.button>
);
}
```
### Pattern 4: Staggered List Entrance
```javascript
// Framer Motion
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1 // 100ms delay between children
}
}
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.3 }
}
};
<motion.ul
variants={containerVariants}
initial="hidden"
animate="visible"
>
{items.map(item => (
<motion.li key={item.id} variants={itemVariants}>
{item.content}
</motion.li>
))}
</motion.ul>
```
### Pattern 5: Modal Enter/Exit
```javascript
// Framer Motion with AnimatePresence
const backdropVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 }
};
const modalVariants = {
hidden: {
opacity: 0,
scale: 0.95,
y: 20
},
visible: {
opacity: 1,
scale: 1,
y: 0,
transition: {
duration: 0.3,
ease: [0, 0, 0.2, 1]
}
},
exit: {
opacity: 0,
scale: 0.95,
transition: {
duration: 0.2,
ease: [0.4, 0, 1, 1]
}
}
};
<AnimatePresence>
{isOpen && (
<>
<motion.div
className="backdrop"
variants={backdropVariants}
initial="hidden"
animate="visible"
exit="hidden"
/>
<motion.div
className="modal"
variants={modalVariants}
initial="hidden"
animate="visible"
exit="exit"
>
Modal content
</motion.div>
</>
)}
</AnimatePresence>
```
## Multi-Element Choreography
When animating multiple elements, follow the **hierarchy → stagger → overlap** principle:
### Hierarchy Rules
1. **Most important first** — Hero content enters before supporting elements
2. **Follow reading order** — Respect natural eye flow (top→bottom, left→right)
3. **Group by relationship** — Related elements move together
### Stagger Timing
```javascript
// Small gaps (snappy)
staggerChildren: 0.05 // 50ms
// Medium gaps (balanced)
staggerChildren: 0.1 // 100ms
// Large gaps (dramatic)
staggerChildren: 0.15 // 150ms
```
### Choreography Example: Dashboard Entry
```javascript
// 1. Hero chart enters first
// 2. Stats cards stagger in
// 3. Sidebar fades in last
const dashboardVariants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.1,
delayChildren: 0.2 // Wait for hero
}
}
};
<motion.div variants={dashboardVariants} initial="hidden" animate="visible">
{/* Hero enters immediately */}
<motion.div variants={heroVariants}>
<Chart />
</motion.div>
{/* Cards stagger after hero */}
<motion.div variants={containerVariants}>
{cards.map(card => (
<motion.div key={card.id} variants={cardVariants}>
{card.content}
</motion.div>
))}
</motion.div>
{/* Sidebar fades in last */}
<motion.aside variants={sidebarVariants}>
<Sidebar />
</motion.aside>
</motion.div>
```
## Disney's 12 Principles (UI-Adapted)
### 1. Squash & Stretch
**UI Application:** Scale feedback on interactive elements
```javascript
// Button press
whileTap={{ scale: 0.95 }}
```
### 2. Anticipation
**UI Application:** Subtle motion before main action
```javascript
// Button hover primes for click
hover: { scale: 1.05, y: -2 }
```
### 3. Staging
**UI Application:** Focus attention through contrast
Voir sur GitHub