Animation Components
Animation Components
Section titled “Animation Components”Purpose
Section titled “Purpose”Animation components provide pre-configured Framer Motion wrappers for common animation patterns like fade-in, slide, and scale effects.
Public API
Section titled “Public API”MotionViewport
Section titled “MotionViewport”Animates children when they enter viewport.
interface MotionViewportProps { children: ReactNode; disableAnimate?: boolean;}MotionContainer
Section titled “MotionContainer”Container for staggered child animations.
interface MotionContainerProps { children: ReactNode; action?: boolean; animate?: boolean;}varFade
Section titled “varFade”Fade animation variants.
const varFade = { in: { ... }, // Fade in inUp: { ... }, // Fade in from bottom inDown: { ... }, // Fade in from top inLeft: { ... }, // Fade in from left inRight: { ... }, // Fade in from right out: { ... }, // Fade out outUp: { ... }, // Fade out upward outDown: { ... }, // Fade out downward outLeft: { ... }, // Fade out left outRight: { ... }, // Fade out right};varZoom
Section titled “varZoom”Zoom/scale animation variants.
const varZoom = { in: { ... }, // Zoom in inUp: { ... }, // Zoom in from bottom inDown: { ... }, // Zoom in from top inLeft: { ... }, // Zoom in from left inRight: { ... }, // Zoom in from right out: { ... }, // Zoom out};Fade In on Scroll
Section titled “Fade In on Scroll”import { m } from 'framer-motion';import { MotionViewport, varFade } from 'src/components/animate';
function HeroSection() { return ( <MotionViewport> <m.div variants={varFade().inUp}> <Typography variant="h1">Welcome to RednGift</Typography> </m.div>
<m.div variants={varFade().inUp}> <Typography variant="body1"> Organize your Secret Santa events effortlessly </Typography> </m.div> </MotionViewport> );}Staggered List Animation
Section titled “Staggered List Animation”import { m } from 'framer-motion';import { MotionContainer, varFade } from 'src/components/animate';
function GroupsList({ groups }: Props) { return ( <MotionContainer> {groups.map((group, index) => ( <m.div key={group.id} variants={varFade().inUp} transition={{ delay: index * 0.1 }} > <GroupCard group={group} /> </m.div> ))} </MotionContainer> );}Button Hover Effect
Section titled “Button Hover Effect”import { m } from 'framer-motion';
function AnimatedButton() { return ( <m.button whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} transition={{ type: 'spring', stiffness: 300 }} > Create Group </m.button> );}Page Transition
Section titled “Page Transition”import { m } from 'framer-motion';import { varFade } from 'src/components/animate';
function PageWrapper({ children }: Props) { return ( <m.div initial="initial" animate="animate" exit="exit" variants={varFade().in} > {children} </m.div> );}Behavior and Constraints
Section titled “Behavior and Constraints”- Performance: Uses GPU-accelerated transforms (translate, scale, opacity)
- Lazy loading: MotionLazy component defers Framer Motion loading
- Accessibility: Respects
prefers-reduced-motionmedia query - Viewport detection: Uses Intersection Observer for scroll animations
Testing
Section titled “Testing”it('should animate on mount', () => { const { container } = render( <m.div variants={varFade().inUp}> <p>Content</p> </m.div> );
// Check initial state expect(container.firstChild).toHaveStyle({ opacity: 0 });
// Wait for animation await waitFor(() => { expect(container.firstChild).toHaveStyle({ opacity: 1 }); });});Further Reading
Section titled “Further Reading”- Framer Motion Documentation - Official docs