# Motion Specification Template
Detailed animation specifications for consistent motion design across projects.
## Easing Curves
### Standard Easings
**Ease-out (Entrances)**
```css
cubic-bezier(0.0, 0.0, 0.2, 1)
```
Use for: Elements entering view, expanding, appearing
**Ease-in (Exits)**
```css
cubic-bezier(0.4, 0.0, 1, 1)
```
Use for: Elements leaving view, collapsing, disappearing
**Ease-in-out (Transitions)**
```css
cubic-bezier(0.4, 0.0, 0.2, 1)
```
Use for: State changes, transformations, element swaps
**Linear (Continuous)**
```css
linear
```
Use for: Loading spinners, continuous animations, marquee scrolls
### Custom Easings
**Spring (Bouncy)**
```css
cubic-bezier(0.68, -0.55, 0.265, 1.55)
```
Use for: Playful interactions, game-like UIs, attention-grabbing
**Sharp (Quick snap)**
```css
cubic-bezier(0.4, 0.0, 0.6, 1)
```
Use for: Mechanical interactions, precise movements
## Duration Tables
### By Interaction Type
| Interaction | Duration | Easing | Example |
|-------------|----------|--------|---------|
| Button press | 100ms | ease-out | Background color change |
| Hover state | 150ms | ease-out | Underline appearing |
| Checkbox toggle | 150ms | ease-out | Checkmark animation |
| Tooltip appear | 200ms | ease-out | Tooltip fade in |
| Tab switch | 250ms | ease-in-out | Content swap |
| Accordion expand | 300ms | ease-out | Height animation |
| Modal open | 300ms | ease-out | Fade + scale up |
| Modal close | 250ms | ease-in | Fade + scale down |
| Page transition | 400ms | ease-in-out | Route change |
| Sheet slide-in | 300ms | ease-out | Bottom sheet |
| Toast notification | 300ms | ease-out | Slide in from top |
### By Element Weight
| Element Weight | Duration | Example |
|----------------|----------|---------|
| Lightweight (< 100px) | 150ms | Icons, badges, chips |
| Standard (100-500px) | 300ms | Cards, panels, list items |
| Weighty (> 500px) | 500ms | Modals, full-page transitions |
## State-Specific Animations
### Hover States
**Button Hover:**
```tsx
// Tailwind
// Framer Motion
Hover Me
```
**Link Hover:**
```tsx
Link Text
```
**Card Hover:**
```tsx
Card Content
```
### Focus States
**Keyboard Focus:**
```tsx
```
**Input Focus:**
```tsx
```
### Active/Pressed States
**Button Press:**
```tsx
Press Me
// CSS alternative
```
### Disabled States
**Disabled Button:**
```tsx
```
### Loading States
**Loading Spinner:**
```tsx
// CSS
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: spin 1s linear infinite;
}
```
**Skeleton Loader:**
```tsx
// CSS
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
```
### Success Feedback
**Checkmark Animation:**
```tsx
```
**Toast Notification:**
```tsx
Success! Changes saved.
```
### Error Feedback
**Shake Animation:**
```tsx
// CSS alternative
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-4px); }
40%, 80% { transform: translateX(4px); }
}
.shake {
animation: shake 0.3s ease-in-out;
}
```
**Error Message Slide-in:**
```tsx
Please enter a valid email address
```
### Warning Feedback
**Pulse Animation:**
```tsx
Warning Content
```
### Form Validation
**Field Validation (On Blur):**
```tsx
// Validate on blur, not during typing
{
const isValid = validateEmail(e.target.value);
setError(!isValid);
}}
className={`
border-2 transition-all duration-200 ease-out
${error
? 'border-red-500 focus:ring-red-200'
: 'border-slate-300 focus:ring-blue-200'
}
`}
/>
{error && (
Please enter a valid email
)}
```
## Common Animation Patterns
### Fade In
```tsx
// Framer Motion
Content
// CSS
.fade-in {
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
```
### Slide Up
```tsx
// Framer Motion
Content
// CSS
.slide-up {
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
```
### Scale + Fade (Modal)
```tsx
// Framer Motion
Modal content
```
### Stagger Children
```tsx
// Framer Motion
{items.map(item => (
{item.name}
))}
```
## Performance Checklist
- [ ] Only animate `transform` and `opacity`
- [ ] Avoid animating `width`, `height`, `top`, `left`, `margin`, `padding`
- [ ] Test on mobile devices (target 60fps)
- [ ] Use `will-change` only for complex animations
- [ ] Implement `prefers-reduced-motion` media query
- [ ] Keep animation duration under 500ms for UI interactions
- [ ] Use CSS animations for simple transitions (better performance)
- [ ] Use JS animation libraries for complex, choreographed sequences
## Accessibility
```css
/* Disable or reduce animations for users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
**Implementation in React:**
```tsx
import { useReducedMotion } from 'framer-motion';
function MyComponent() {
const shouldReduceMotion = useReducedMotion();
return (
Content
);
}
```
## Testing Animations
1. **Test at 60fps** on target devices
2. **Test with slow network** (does page still feel responsive?)
3. **Test with reduced motion** preferences enabled
4. **Verify animations don't block** critical user actions
5. **Check that animations add value** (remove if purely decorative)
6. **Test on low-end devices** (not just your development machine)
7. **Measure performance** with Chrome DevTools Performance tab
8. **Check for layout thrashing** (avoid reading and writing to DOM in same frame)
## Animation & Gestalt Principles
### Proximity
Animated elements that are near each other should move together to reinforce grouping:
```tsx
// Animate card and its children together
Title
Content
```
### Similarity
Similar elements should have similar animation characteristics:
```tsx
// All buttons use same hover animation
const buttonAnimation = {
whileHover: { scale: 1.02 },
transition: { duration: 0.15, ease: "easeOut" }
};
Button 1
Button 2
```
### Continuity
Movement should follow natural, smooth paths:
```tsx
// Smooth curve, not jumpy angles
```
### Figure-Ground
Important elements animate while backgrounds stay stable:
```tsx
// Background fades out, modal animates in
<>
Modal Content
>
```
## Resources
- [Framer Motion Documentation](https://www.framer.com/motion/)
- [CSS Easing Functions](https://easings.net/)
- [Material Design Motion](https://m2.material.io/design/motion/)
- [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API)