Spaces:
Sleeping
Sleeping
| "use client"; | |
| import { motion, type Variants } from "framer-motion"; | |
| import type { ReactNode } from "react"; | |
| /* βββ Fade-up stagger container βββ */ | |
| const containerVariants: Variants = { | |
| hidden: {}, | |
| show: { transition: { staggerChildren: 0.06, delayChildren: 0.1 } }, | |
| }; | |
| const itemVariants: Variants = { | |
| hidden: { opacity: 0, y: 24, filter: "blur(4px)" }, | |
| show: { | |
| opacity: 1, | |
| y: 0, | |
| filter: "blur(0px)", | |
| transition: { duration: 0.5, ease: [0.25, 0.46, 0.45, 0.94] }, | |
| }, | |
| }; | |
| export function StaggerContainer({ | |
| children, | |
| className, | |
| }: { | |
| children: ReactNode; | |
| className?: string; | |
| }) { | |
| return ( | |
| <motion.div | |
| variants={containerVariants} | |
| initial="hidden" | |
| animate="show" | |
| className={className} | |
| > | |
| {children} | |
| </motion.div> | |
| ); | |
| } | |
| export function StaggerItem({ | |
| children, | |
| className, | |
| }: { | |
| children: ReactNode; | |
| className?: string; | |
| }) { | |
| return ( | |
| <motion.div variants={itemVariants} className={className}> | |
| {children} | |
| </motion.div> | |
| ); | |
| } | |
| /* βββ Fade in (standalone) βββ */ | |
| export function FadeIn({ | |
| children, | |
| className, | |
| delay = 0, | |
| direction = "up", | |
| }: { | |
| children: ReactNode; | |
| className?: string; | |
| delay?: number; | |
| direction?: "up" | "down" | "left" | "right" | "none"; | |
| }) { | |
| const offsets = { | |
| up: { y: 30 }, | |
| down: { y: -30 }, | |
| left: { x: 30 }, | |
| right: { x: -30 }, | |
| none: {}, | |
| }; | |
| return ( | |
| <motion.div | |
| initial={{ opacity: 0, filter: "blur(4px)", ...offsets[direction] }} | |
| animate={{ opacity: 1, filter: "blur(0px)", x: 0, y: 0 }} | |
| transition={{ | |
| duration: 0.6, | |
| delay, | |
| ease: [0.25, 0.46, 0.45, 0.94], | |
| }} | |
| className={className} | |
| > | |
| {children} | |
| </motion.div> | |
| ); | |
| } | |
| /* βββ Animated counter βββ */ | |
| export { AnimatedCounter } from "./AnimatedCounter"; | |
| /* βββ Hover card βββ */ | |
| export function HoverCard({ | |
| children, | |
| className, | |
| }: { | |
| children: ReactNode; | |
| className?: string; | |
| }) { | |
| return ( | |
| <motion.div | |
| whileHover={{ | |
| y: -4, | |
| transition: { duration: 0.2, ease: "easeOut" }, | |
| }} | |
| className={className} | |
| > | |
| {children} | |
| </motion.div> | |
| ); | |
| } | |
| /* βββ Scale on tap βββ */ | |
| export function ScaleTap({ | |
| children, | |
| className, | |
| }: { | |
| children: ReactNode; | |
| className?: string; | |
| }) { | |
| return ( | |
| <motion.div | |
| whileTap={{ scale: 0.97 }} | |
| className={className} | |
| > | |
| {children} | |
| </motion.div> | |
| ); | |
| } | |