nicholais-website/components/motion/SplitTextReveal.tsx

67 lines
1.4 KiB
TypeScript

"use client";
import React from "react";
import { motion } from "motion/react";
import type { Variants } from "motion/react";
import { TRANSITIONS } from "@/lib/animation";
type SplitTextRevealProps = {
text: string;
className?: string;
once?: boolean;
wordClassName?: string;
stagger?: number;
};
export function SplitTextReveal({
text,
className,
once = true,
wordClassName,
stagger = 0.06,
}: SplitTextRevealProps) {
const words = text.trim().split(/\s+/);
const container: Variants = {
initial: {},
animate: {
transition: {
staggerChildren: stagger,
},
},
};
const child: Variants = {
initial: { opacity: 0, y: 8, filter: "blur(6px)" },
animate: {
opacity: 1,
y: 0,
filter: "blur(0px)",
transition: TRANSITIONS.base,
},
};
return (
<motion.span
className={className}
style={{ display: "inline-block" }}
variants={container}
initial="initial"
whileInView="animate"
viewport={{ once, margin: "0px 0px -10% 0px" }}
>
{words.map((w, i) => (
<motion.span
key={`${w}-${i}`}
className={wordClassName}
style={{ display: "inline-block", willChange: "transform" }}
variants={child}
>
{w}
{i < words.length - 1 ? " " : ""}
</motion.span>
))}
</motion.span>
);
}