framer-motion-animations
Framer Motion Animations
Installation
npm install framer-motion
Basic Fade In
'use client';
import { motion } from 'framer-motion';
export function FadeIn({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
{children}
</motion.div>
);
}
Staggered Children
'use client';
import { motion } from 'framer-motion';
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
};
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
};
export function StaggeredList({ items }: { items: React.ReactNode[] }) {
return (
<motion.ul
variants={container}
initial="hidden"
animate="show"
className="space-y-4"
>
{items.map((child, i) => (
<motion.li key={i} variants={item}>
{child}
</motion.li>
))}
</motion.ul>
);
}
Scroll-Triggered Animation
'use client';
import { motion, useInView } from 'framer-motion';
import { useRef } from 'react';
export function ScrollReveal({ children }: { children: React.ReactNode }) {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: '-100px' });
return (
<motion.div
ref={ref}
initial={{ opacity: 0, y: 50 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 50 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
>
{children}
</motion.div>
);
}
Hero Animation
'use client';
import { motion } from 'framer-motion';
export function HeroSection() {
return (
<section className="min-h-screen flex items-center">
<div className="container mx-auto px-4">
<motion.h1
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="text-5xl md:text-7xl font-bold"
>
Pilates & Yoga
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
className="text-xl mt-6 text-muted-foreground"
>
Transform your body and mind
</motion.p>
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
className="mt-8 flex gap-4"
>
<Button>Book Now</Button>
<Button variant="outline">Learn More</Button>
</motion.div>
</div>
</section>
);
}
Card Hover Effect
'use client';
import { motion } from 'framer-motion';
export function AnimatedCard({ children }: { children: React.ReactNode }) {
return (
<motion.div
whileHover={{ y: -5, boxShadow: '0 10px 30px rgba(0,0,0,0.1)' }}
transition={{ duration: 0.2 }}
className="bg-card rounded-lg p-6 border"
>
{children}
</motion.div>
);
}
Section Wrapper
'use client';
import { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
import { useRef } from 'react';
interface SectionProps {
children: React.ReactNode;
className?: string;
delay?: number;
}
export function AnimatedSection({ children, className, delay = 0 }: SectionProps) {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: '-50px' });
return (
<motion.section
ref={ref}
initial={{ opacity: 0, y: 40 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay, ease: 'easeOut' }}
className={className}
>
{children}
</motion.section>
);
}
Counter Animation
'use client';
import { motion, useMotionValue, useTransform, animate } from 'framer-motion';
import { useEffect } from 'react';
interface CounterProps {
from: number;
to: number;
duration?: number;
}
export function AnimatedCounter({ from, to, duration = 2 }: CounterProps) {
const count = useMotionValue(from);
const rounded = useTransform(count, (latest) => Math.round(latest));
useEffect(() => {
const controls = animate(count, to, { duration });
return controls.stop;
}, [count, to, duration]);
return <motion.span>{rounded}</motion.span>;
}
// Usage
<div className="text-4xl font-bold">
<AnimatedCounter from={0} to={500} />+
<span className="text-sm">Happy Clients</span>
</div>
Page Transition Wrapper
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { usePathname } from 'next/navigation';
export function PageTransition({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
<AnimatePresence mode="wait">
<motion.div
key={pathname}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
>
{children}
</motion.div>
</AnimatePresence>
);
}
Accordion Animation
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { useState } from 'react';
interface AccordionItemProps {
title: string;
children: React.ReactNode;
}
export function AccordionItem({ title, children }: AccordionItemProps) {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="border-b">
<button
onClick={() => setIsOpen(!isOpen)}
className="w-full py-4 flex justify-between items-center"
>
<span className="font-medium">{title}</span>
<motion.span
animate={{ rotate: isOpen ? 180 : 0 }}
transition={{ duration: 0.2 }}
>
▼
</motion.span>
</button>
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
className="overflow-hidden"
>
<div className="pb-4">{children}</div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}
Performance Tips
- Use
layoutIdfor shared element transitions - Use
useReducedMotion()to respect user preferences - Avoid animating layout properties (width, height) - use transforms
- Use
will-changesparingly via Tailwind'swill-change-transform - Prefer
opacityandtransformanimations (GPU accelerated)
More from canatufkansu/claude-skills
next-intl-i18n
next-intl internationalization for 6 locales (pt-PT, en, tr, es, fr, de) with locale-prefixed routing, useTranslations/getTranslations patterns, and message file structure. Use when adding translations, creating localized pages, implementing language switchers, or handling locale routing.
42sitemap-robots
Automated sitemap generation for all locale URLs, robots.txt configuration, and llms.txt for AI crawler optimization. Use when setting up sitemap.xml, configuring crawling rules, or improving discoverability for search engines and AI systems.
35tailwind-shadcn
Tailwind CSS utility patterns with shadcn/ui component usage, theming via CSS variables, and responsive design. Use when styling components, installing shadcn components, implementing dark mode, or creating consistent design systems.
29json-ld-schemas
JSON-LD structured data for Organization, Person, Service, Product, FAQPage, and BreadcrumbList with reusable components. Use when implementing schema.org markup, adding rich snippets, or improving search engine understanding of page content.
22responsive-mobile-first
Mobile-first responsive patterns with sticky headers, floating CTAs, accessible navigation, and touch-friendly interactions. Use when implementing responsive layouts, mobile navigation, or ensuring touch-friendly UI.
12theme-system
CSS custom properties theme architecture for 4 themes (studio, earth, athlete, gradient) with data-theme attribute switching and theme-aware components. Use when implementing theme switching, defining color schemes, or creating theme-responsive UI elements.
11