--- name: animation-patterns description: Framer Motion patterns, page transitions, skeleton loading, scroll-linked animations, and gesture-based interactions for React. --- # Animation Patterns Framer Motion patterns for production-quality React animations. ## Framer Motion Basics (motion components, variants) ```typescript // Install: npm install framer-motion import { motion } from 'framer-motion' // Basic motion component // Variants — define states, animate by name const cardVariants = { hidden: { opacity: 0, y: 20, scale: 0.98 }, visible: { opacity: 1, y: 0, scale: 1, transition: { duration: 0.25, ease: [0.16, 1, 0.3, 1] }, }, hover: { y: -4, boxShadow: '0 12px 24px -4px rgb(0 0 0 / 0.15)', transition: { duration: 0.2 }, }, } function Card({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` ## Page Transitions with AnimatePresence ```typescript import { AnimatePresence, motion } from 'framer-motion' import { usePathname } from 'next/navigation' const pageVariants = { initial: { opacity: 0, x: -8 }, enter: { opacity: 1, x: 0, transition: { duration: 0.2, ease: 'easeOut' } }, exit: { opacity: 0, x: 8, transition: { duration: 0.15, ease: 'easeIn' } }, } // app/layout.tsx (Next.js App Router) export default function RootLayout({ children }: { children: React.ReactNode }) { const pathname = usePathname() return ( {children} ) } // Modal transitions — mount/unmount function Modal({ isOpen, onClose, children }: ModalProps) { return ( {isOpen && ( <> {children} )} ) } ``` ## Layout Animations (Shared Layout, Layout ID) ```typescript import { motion, LayoutGroup } from 'framer-motion' import { useState } from 'react' // Tabs with animated indicator function AnimatedTabs({ tabs }: { tabs: string[] }) { const [active, setActive] = useState(tabs[0]) return (
{tabs.map(tab => ( ))}
) } // Expandable card with layout animation function ExpandableCard({ title, body }: { title: string; body: string }) { const [expanded, setExpanded] = useState(false) return ( setExpanded(e => !e)} > {title} {expanded && ( {body} )} ) } ``` ## Skeleton Loading Components ```typescript // Base skeleton primitive function Skeleton({ className }: { className?: string }) { return (