# 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)