Files
DetnalCare/components/ui/shimmering-text.tsx
Iliyan Angelov 39077550ef Dental Care
2025-11-16 14:29:51 +02:00

81 lines
2.0 KiB
TypeScript

"use client";
import * as React from "react";
import { type HTMLMotionProps, motion, type Transition } from "motion/react";
import { cn } from "@/lib/utils";
type ShimmeringTextProps = {
text: string;
duration?: number;
transition?: Transition;
wave?: boolean;
color?: string;
shimmeringColor?: string;
} & Omit<HTMLMotionProps<"span">, "children">;
function ShimmeringText({
text,
duration = 1,
transition,
wave = false,
className,
color = "var(--color-neutral-500)",
shimmeringColor = "var(--color-neutral-300)",
...props
}: ShimmeringTextProps) {
return (
<motion.span
className={cn("relative inline-block [perspective:500px]", className)}
style={
{
"--shimmering-color": shimmeringColor,
"--color": color,
color: "var(--color)",
} as React.CSSProperties
}
{...props}
>
{text?.split("")?.map((char, i) => (
<motion.span
key={i}
className="inline-block whitespace-pre [transform-style:preserve-3d]"
initial={{
...(wave
? {
scale: 1,
rotateY: 0,
}
: {}),
color: "var(--color)",
}}
animate={{
...(wave
? {
x: [0, 5, 0],
y: [0, -5, 0],
scale: [1, 1.1, 1],
rotateY: [0, 15, 0],
}
: {}),
color: ["var(--color)", "var(--shimmering-color)", "var(--color)"],
}}
transition={{
duration,
repeat: Infinity,
repeatType: "loop",
repeatDelay: text.length * 0.05,
delay: (i * duration) / text.length,
ease: "easeInOut",
...transition,
}}
>
{char}
</motion.span>
))}
</motion.span>
);
}
export { ShimmeringText, type ShimmeringTextProps };