Files

56 lines
1.6 KiB
TypeScript
Raw Permalink Normal View History

2026-08-18 18:33:49 -07:00
'use client'
import { motion } from 'framer-motion'
import { useState, useEffect } from 'react'
const phrases = [
'a Senior Systems engineer',
'Rock Liang',
'a Senior Full-stack builder',
'a Senior Infrastructure architect',
'a Senior Backend SDE',
]
export function TypewriterText() {
const [currentPhrase, setCurrentPhrase] = useState(0)
const [displayText, setDisplayText] = useState('')
const [isDeleting, setIsDeleting] = useState(false)
useEffect(() => {
const phrase = phrases[currentPhrase]
const delay = isDeleting ? 50 : 100
const timer = setTimeout(() => {
if (!isDeleting) {
if (displayText.length < phrase.length) {
setDisplayText(phrase.substring(0, displayText.length + 1))
} else {
setTimeout(() => setIsDeleting(true), 1500)
}
} else {
if (displayText.length > 0) {
setDisplayText(phrase.substring(0, displayText.length - 1))
} else {
setIsDeleting(false)
setCurrentPhrase((prev) => (prev + 1) % phrases.length)
}
}
}, delay)
return () => clearTimeout(timer)
}, [displayText, isDeleting, currentPhrase])
return (
<div className="relative z-10 mt-6 h-10 flex items-center justify-center">
<span className="text-2xl font-semibold text-gray-800 dark:text-gray-200">
I'm <span className="text-blue-600 dark:text-blue-400">{displayText}</span>
<motion.span
animate={{ opacity: [1, 0] }}
transition={{ duration: 0.6, repeat: Infinity }}
className="inline-block w-0.5 h-7 ml-1 bg-blue-600 dark:bg-blue-400"
/>
</span>
</div>
)
}