44 lines
839 B
TypeScript
44 lines
839 B
TypeScript
"use client";
|
|
|
|
import { motion } from "motion/react";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export function TypewriterText({
|
|
text,
|
|
className,
|
|
}: {
|
|
text: string;
|
|
className?: string;
|
|
}) {
|
|
const [displayed, setDisplayed] = useState(text[0] ?? "");
|
|
const [done, setDone] = useState(text.length <= 1);
|
|
|
|
useEffect(() => {
|
|
setDisplayed(text[0] ?? "");
|
|
setDone(text.length <= 1);
|
|
let i = 1;
|
|
const id = setInterval(() => {
|
|
if (i < text.length) {
|
|
setDisplayed(text.slice(0, i + 1));
|
|
i++;
|
|
} else {
|
|
clearInterval(id);
|
|
setDone(true);
|
|
}
|
|
}, 40);
|
|
return () => clearInterval(id);
|
|
}, [text]);
|
|
|
|
return (
|
|
<>
|
|
<span className="sr-only">{text}</span>
|
|
<motion.span
|
|
className={`${className ?? ""} ${!done ? "typing-cursor" : ""}`}
|
|
aria-hidden
|
|
>
|
|
{displayed}
|
|
</motion.span>
|
|
</>
|
|
);
|
|
}
|