import type { Variants } from "motion/react"; // Base transition configurations for consistent animations const baseTransition = { duration: 0.5, ease: [0.43, 0.13, 0.23, 0.96], // Improved easing for smoother feel }; export const fadeTransition = { ...baseTransition, duration: 0.3, }; // Shared variants for different view levels export const containerVariants: Variants = { text: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, paragraph: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, sentence: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, clause: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, word: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, syllable: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, phoneme: { opacity: 1, transition: { staggerChildren: 0.05, delayChildren: 0.1, }, }, }; // Function to create element variants based on selection state export const createElementVariants = ( currentLevel: string, nextLevel: string, prevLevel: string, selectedOpacity = 1, unselectedOpacity = 0.1, selectedScale = 1.05, unselectedScale = 0.95, selectedBlur = "0px", unselectedBlur = "2px", bgColor = "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity instead of transparent ): Variants => { return { [prevLevel]: { opacity: 1, scale: 1, filter: "blur(0px)", backgroundColor: "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity transition: baseTransition, }, [currentLevel]: (isSelected: boolean) => ({ opacity: isSelected ? selectedOpacity : unselectedOpacity, scale: isSelected ? selectedScale : unselectedScale, filter: isSelected ? `blur(${selectedBlur})` : `blur(${unselectedBlur})`, backgroundColor: isSelected ? bgColor : "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity transition: baseTransition, }), [nextLevel]: (isSelected: boolean) => ({ opacity: isSelected ? selectedOpacity : unselectedOpacity / 2, scale: isSelected ? selectedScale : unselectedScale * 0.95, filter: isSelected ? `blur(${selectedBlur})` : `blur(${parseInt(unselectedBlur) + 1}px)`, backgroundColor: isSelected ? bgColor : "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity transition: baseTransition, }), }; }; // Pre-configured variants for each level export const paragraphVariants = createElementVariants( "paragraph", "sentence", "text", 1, 0.1, 1.05, 0.95, "0px", "2px", "rgba(200, 220, 255, 0.1)", ); export const sentenceVariants = createElementVariants( "sentence", "clause", "paragraph", 1, 0.1, 1.1, 0.95, "0px", "2px", "rgba(200, 220, 255, 0.2)", ); export const clauseVariants = createElementVariants( "clause", "word", "sentence", 1, 0.1, 1.1, 0.95, "0px", "2px", "rgba(220, 200, 255, 0.2)", ); export const wordVariants = createElementVariants( "word", "syllable", "clause", 1, 0.1, 1.15, 0.9, "0px", "2px", "rgba(255, 200, 200, 0.2)", ); export const syllableVariants = createElementVariants( "syllable", "phoneme", "word", 1, 0.1, 1.2, 0.9, "0px", "2px", "rgba(200, 255, 200, 0.2)", ); // Button animations export const buttonVariants: Variants = { initial: { opacity: 0, x: -20 }, animate: { opacity: 1, x: 0, transition: fadeTransition }, exit: { opacity: 0, x: -20, transition: fadeTransition }, }; // Hover effects export const createHoverEffect = ( level: string, currentLevel: string, color: string, ) => { if (level === currentLevel) { return { scale: 1.02, backgroundColor: `rgba(${color}, 0.3)`, transition: { duration: 0.2 }, }; } return { // Return empty animation with same properties to avoid errors scale: 1, backgroundColor: "rgba(255, 255, 255, 0)", transition: { duration: 0.2 }, }; };