Spaces:
Sleeping
Sleeping
| "use client"; | |
| import type { Transition, Variants } from "framer-motion"; | |
| /** | |
| * Spring-based easing functions matching the CSS tokens | |
| */ | |
| export const springTransition: Transition = { | |
| type: "spring", | |
| stiffness: 300, | |
| damping: 30, | |
| }; | |
| export const gentleSpring: Transition = { | |
| type: "spring", | |
| stiffness: 200, | |
| damping: 25, | |
| }; | |
| export const bouncySpring: Transition = { | |
| type: "spring", | |
| stiffness: 400, | |
| damping: 20, | |
| }; | |
| /** | |
| * Animation variants for entrance animations | |
| */ | |
| export const fadeIn: Variants = { | |
| hidden: { opacity: 0 }, | |
| visible: { | |
| opacity: 1, | |
| transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] }, | |
| }, | |
| }; | |
| export const fadeInUp: Variants = { | |
| hidden: { opacity: 0, y: 20 }, | |
| visible: { | |
| opacity: 1, | |
| y: 0, | |
| transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| }; | |
| export const fadeInScale: Variants = { | |
| hidden: { opacity: 0, scale: 0.95, y: 12 }, | |
| visible: { | |
| opacity: 1, | |
| scale: 1, | |
| y: 0, | |
| transition: { duration: 0.5, ease: [0.34, 1.56, 0.64, 1] }, | |
| }, | |
| }; | |
| export const slideInLeft: Variants = { | |
| hidden: { opacity: 0, x: -20 }, | |
| visible: { | |
| opacity: 1, | |
| x: 0, | |
| transition: { duration: 0.4, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| }; | |
| export const slideInRight: Variants = { | |
| hidden: { opacity: 0, x: 20 }, | |
| visible: { | |
| opacity: 1, | |
| x: 0, | |
| transition: { duration: 0.4, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| }; | |
| /** | |
| * Stagger container variants | |
| */ | |
| export const staggerContainer: Variants = { | |
| hidden: { opacity: 0 }, | |
| visible: { | |
| opacity: 1, | |
| transition: { | |
| staggerChildren: 0.06, | |
| delayChildren: 0.1, | |
| }, | |
| }, | |
| }; | |
| export const staggerContainerFast: Variants = { | |
| hidden: { opacity: 0 }, | |
| visible: { | |
| opacity: 1, | |
| transition: { | |
| staggerChildren: 0.04, | |
| delayChildren: 0.05, | |
| }, | |
| }, | |
| }; | |
| /** | |
| * List item variants for staggered animations | |
| */ | |
| export const listItem: Variants = { | |
| hidden: { opacity: 0, y: 16 }, | |
| visible: { | |
| opacity: 1, | |
| y: 0, | |
| transition: springTransition, | |
| }, | |
| }; | |
| export const listItemSpring: Variants = { | |
| hidden: { opacity: 0, scale: 0.95, y: 12 }, | |
| visible: { | |
| opacity: 1, | |
| scale: 1, | |
| y: 0, | |
| transition: { duration: 0.5, ease: [0.34, 1.56, 0.64, 1] }, | |
| }, | |
| }; | |
| /** | |
| * Page transition variants | |
| */ | |
| export const pageTransition: Variants = { | |
| hidden: { opacity: 0, y: 8 }, | |
| visible: { | |
| opacity: 1, | |
| y: 0, | |
| transition: { duration: 0.35, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| exit: { | |
| opacity: 0, | |
| y: -8, | |
| transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| }; | |
| /** | |
| * Hover scale variant for interactive elements | |
| */ | |
| export const hoverScale: Variants = { | |
| rest: { scale: 1 }, | |
| hover: { | |
| scale: 1.02, | |
| transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] }, | |
| }, | |
| tap: { | |
| scale: 0.98, | |
| transition: { duration: 0.1 }, | |
| }, | |
| }; | |
| /** | |
| * Glow pulse variant for accent elements | |
| */ | |
| export const glowPulse: Variants = { | |
| initial: { opacity: 0.6 }, | |
| animate: { | |
| opacity: [0.6, 1, 0.6], | |
| transition: { | |
| duration: 2, | |
| repeat: Infinity, | |
| ease: "easeInOut", | |
| }, | |
| }, | |
| }; | |
| /** | |
| * Draw line variant for SVG paths | |
| */ | |
| export const drawLine: Variants = { | |
| hidden: { pathLength: 0, opacity: 0 }, | |
| visible: { | |
| pathLength: 1, | |
| opacity: 1, | |
| transition: { duration: 1.2, ease: [0.4, 0, 0.2, 1] }, | |
| }, | |
| }; | |
| /** | |
| * Ambient float animation | |
| */ | |
| export const float: Variants = { | |
| initial: { y: 0 }, | |
| animate: { | |
| y: [-4, 4, -4], | |
| transition: { | |
| duration: 6, | |
| repeat: Infinity, | |
| ease: "easeInOut", | |
| }, | |
| }, | |
| }; | |
| /** | |
| * Reduced motion check helper | |
| * Returns true if user prefers reduced motion | |
| */ | |
| export function prefersReducedMotion(): boolean { | |
| if (typeof window === "undefined") return false; | |
| return window.matchMedia("(prefers-reduced-motion: reduce)").matches; | |
| } | |