--- name: frontend-lottie description: Decorative JSON animations for UI feedback and polish. Use for loading spinners, success/error checkmarks, empty state illustrations, animated icons. Just plays and loops - no interactivity. For reactive/stateful animations use Rive instead. Lightweight and SSR-compatible. allowed-tools: Read, Edit, Write, Bash (*) --- # Lottie Lightweight vector animations. Just plays and loops — no complex logic. ## When to Use - Loading spinners - Success/error checkmarks - Empty state illustrations - Decorative micro-animations - Animated icons ## When NOT to Use - Animation reacts to input → Rive - Multiple states/transitions → Rive - Complex interactivity → Rive ## Process **FIND → ADD → INTEGRATE** 1. Find animation: https://lottiefiles.com 2. Download .lottie or .json 3. Place in `public/animations/` 4. Use component ## Quick Start ```bash npm install @lottiefiles/dotlottie-react ``` ```tsx import { DotLottieReact } from '@lottiefiles/dotlottie-react'; // Simple autoplay ``` ## Common Patterns ```tsx // Loading spinner // Success feedback (plays once) // Empty state

No results found

// Loading button {isLoading ? ( ) : ( "Submit" )} ``` ## Decision: Lottie vs Rive | Animation Type | Use | |----------------|-----| | Just plays/loops | Lottie ✓ | | Reacts to hover/click | Rive | | State machine | Rive | | Data-driven | Rive | | Simple loader | Lottie ✓ | ## Finding Animations ```yaml LottieFiles: https://lottiefiles.com/free-animations Lordicon: https://lordicon.com (animated icons) useAnimations: https://useanimations.com (micro-interactions) ``` ## Playback Control ```tsx 'use client' import { useState, useCallback } from 'react' import { DotLottieReact, DotLottie } from '@lottiefiles/dotlottie-react' function ControlledLottie() { const [dotLottie, setDotLottie] = useState(null) return (
dotLottie?.play()} onMouseLeave={() => dotLottie?.pause()} >
) } // Methods: play(), pause(), stop(), setSpeed(n), goToAndPlay(frame) ``` ## SSR & Hydration ```tsx // Always 'use client' 'use client' // Dynamic import const DotLottieReact = dynamic( () => import('@lottiefiles/dotlottie-react').then(m => m.DotLottieReact), { ssr: false } ) // Or mounted check const [mounted, setMounted] = useState(false) useEffect(() => setMounted(true), []) if (!mounted) return ``` ## Performance ```tsx // Pause when not visible import { useInView } from 'react-intersection-observer' const { ref, inView } = useInView({ threshold: 0.1 }) useEffect(() => { inView ? dotLottie?.play() : dotLottie?.pause() }, [inView, dotLottie]) ``` ## File Structure ``` public/animations/ loaders/spinner.lottie feedback/success.lottie, error.lottie empty-states/no-data.lottie illustrations/hero.lottie ``` ## Troubleshooting ```yaml "Animation not loading": → Check file path in public/ → Verify .lottie or .json extension "Animation not playing": → Add autoplay={true} → Add loop={true} "Hydration mismatch": → Add 'use client' → Use dynamic(() => ..., { ssr: false }) "Too fast/slow": → speed={0.5} for slower → speed={2} for faster ``` ## References - **[patterns.md](references/patterns.md)** — Controlled playback, events, visibility pause, hover/click triggers ## External Resources - https://lottiefiles.com/free-animations — Free animations - https://useanimations.com — Micro-interactions - https://lordicon.com — Animated icons - For latest API → use context7 skill