33 lines
906 B
TypeScript
33 lines
906 B
TypeScript
import React, { useState, useEffect } from 'react';
|
|
|
|
interface TypingAnimationProps {
|
|
text: string;
|
|
speed?: number;
|
|
onComplete?: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export const TypingAnimation: React.FC<TypingAnimationProps> = ({
|
|
text,
|
|
speed = 30,
|
|
onComplete,
|
|
className = ''
|
|
}) => {
|
|
const [displayedText, setDisplayedText] = useState('');
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (currentIndex < text.length) {
|
|
const timeout = setTimeout(() => {
|
|
setDisplayedText(prev => prev + text[currentIndex]);
|
|
setCurrentIndex(prev => prev + 1);
|
|
}, speed + (Math.random() * 20)); // Add slight randomness for realism
|
|
|
|
return () => clearTimeout(timeout);
|
|
} else if (onComplete) {
|
|
onComplete();
|
|
}
|
|
}, [currentIndex, text, speed, onComplete]);
|
|
|
|
return <span className={className}>{displayedText}</span>;
|
|
}; |