summaryrefslogtreecommitdiff
path: root/src/zoom/animations.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/zoom/animations.ts')
-rw-r--r--src/zoom/animations.ts199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/zoom/animations.ts b/src/zoom/animations.ts
new file mode 100644
index 0000000..6135e7f
--- /dev/null
+++ b/src/zoom/animations.ts
@@ -0,0 +1,199 @@
+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 },
+ };
+};