Skip to content

Animation Components

Animation components provide pre-configured Framer Motion wrappers for common animation patterns like fade-in, slide, and scale effects.

Animates children when they enter viewport.

interface MotionViewportProps {
children: ReactNode;
disableAnimate?: boolean;
}

Container for staggered child animations.

interface MotionContainerProps {
children: ReactNode;
action?: boolean;
animate?: boolean;
}

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
};

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
};
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>
);
}
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>
);
}
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>
);
}
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>
);
}
  • Performance: Uses GPU-accelerated transforms (translate, scale, opacity)
  • Lazy loading: MotionLazy component defers Framer Motion loading
  • Accessibility: Respects prefers-reduced-motion media query
  • Viewport detection: Uses Intersection Observer for scroll animations
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 });
});
});