Text Typing
The TextTyping component creates a classic typewriter effect that reveals text one character at a time, complete with an animated blinking cursor. Perfect for hero sections, introductions, and dynamic content reveals.
Installation
npm install @craftdotui/components
Import
import TextTyping from "@craftdotui/components" ;
Usage
Basic Usage
Custom Speed
As Heading
Slow Dramatic Reveal
import TextTyping from "@craftdotui/components" ;
export default function Example () {
return (
< TextTyping >
Hello, welcome to our website!
</ TextTyping >
);
}
Props
The text to display with the typing animation.
Speed of typing in milliseconds per character. Lower values = faster typing.
Additional CSS classes. Component uses font-mono by default.
Animation Details
Character Reveal
The text is revealed progressively using substring slicing:
useEffect (() => {
let currentIndex = 0 ;
const intervalId = setInterval (() => {
if ( currentIndex <= text . length ) {
setDisplayedText ( text . slice ( 0 , currentIndex ));
currentIndex ++ ;
} else {
clearInterval ( intervalId );
}
}, typingSpeed );
return () => clearInterval ( intervalId );
}, [ text , typingSpeed ]);
Cursor Animation
The cursor uses Framer Motion for smooth blinking:
< motion.span
animate = { { opacity: [ 0 , 1 ] } }
transition = { {
duration: 0.5 ,
repeat: Infinity ,
repeatType: "reverse" ,
} }
>
|
</ motion.span >
The cursor blinks continuously throughout the typing animation and after completion.
Examples
Hero Section
import TextTyping from "@craftdotui/components" ;
export default function Hero () {
return (
< section className = "min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-600 to-blue-600" >
< div className = "text-center" >
< TextTyping
className = "text-5xl md:text-7xl font-bold text-white"
typingSpeed = { 100 }
>
Build Something Amazing
</ TextTyping >
</ div >
</ section >
);
}
Terminal Interface
import TextTyping from "@craftdotui/components" ;
export default function Terminal () {
return (
< div className = "bg-black p-6 rounded-lg" >
< div className = "space-y-2" >
< div className = "text-green-400 font-mono" >
< span className = "text-green-500" > user@system:~$ </ span >
< TextTyping typingSpeed = { 50 } >
npm install @craftdotui/components
</ TextTyping >
</ div >
</ div >
</ div >
);
}
Multi-Line Typing
import { useState , useEffect } from "react" ;
import TextTyping from "@craftdotui/components" ;
export default function MultiLine () {
const [ currentLine , setCurrentLine ] = useState ( 0 );
const lines = [
"Initializing application..." ,
"Loading dependencies..." ,
"Connecting to server..." ,
"Ready!" ,
];
useEffect (() => {
const timer = setTimeout (() => {
if ( currentLine < lines . length - 1 ) {
setCurrentLine ( currentLine + 1 );
}
}, ( lines [ currentLine ]. length * 100 ) + 500 );
return () => clearTimeout ( timer );
}, [ currentLine ]);
return (
< div className = "space-y-2 font-mono" >
{ lines . slice ( 0 , currentLine + 1 ). map (( line , i ) => (
< div key = { i } >
{ i === currentLine ? (
< TextTyping typingSpeed = { 100 } > { line } </ TextTyping >
) : (
< div > { line } </ div >
) }
</ div >
)) }
</ div >
);
}
Code Editor Simulation
import TextTyping from "@craftdotui/components" ;
export default function CodeEditor () {
return (
< div className = "bg-gray-900 rounded-lg p-4" >
< div className = "text-sm" >
< span className = "text-purple-400" > function </ span >
< span className = "text-yellow-300" > greet </ span >
< span className = "text-gray-300" > ( </ span >
< TextTyping
className = "text-orange-400"
typingSpeed = { 80 }
>
name: string
</ TextTyping >
</ div >
</ div >
);
}
Testimonial Reveal
import TextTyping from "@craftdotui/components" ;
import { Quote } from "lucide-react" ;
export default function Testimonial () {
return (
< div className = "max-w-2xl mx-auto p-8 bg-white rounded-lg shadow-lg" >
< Quote className = "w-12 h-12 text-gray-300 mb-4" />
< TextTyping
className = "text-xl text-gray-700 italic"
typingSpeed = { 60 }
>
This product changed the way we work. Highly recommended!
</ TextTyping >
< p className = "mt-4 text-gray-500" > — Jane Doe, CEO </ p >
</ div >
);
}
Interactive Chat Bot
import { useState } from "react" ;
import TextTyping from "@craftdotui/components" ;
export default function ChatBot () {
const [ messages , setMessages ] = useState ([
"Hi! How can I help you today?"
]);
return (
< div className = "max-w-md mx-auto bg-gray-100 rounded-lg p-4" >
{ messages . map (( msg , i ) => (
< div key = { i } className = "mb-3 bg-white p-3 rounded-lg" >
{ i === messages . length - 1 ? (
< TextTyping typingSpeed = { 50 } > { msg } </ TextTyping >
) : (
< div className = "font-mono" > { msg } </ div >
) }
</ div >
)) }
</ div >
);
}
For the most authentic typewriter effect, use monospace fonts like font-mono or custom terminal fonts.
Speed Guidelines
// Very slow (dramatic)
< TextTyping typingSpeed = { 200 } >
// Slow (natural reading pace)
< TextTyping typingSpeed = { 150 } >
// Medium (default)
< TextTyping typingSpeed = { 100 } >
// Fast (energetic)
< TextTyping typingSpeed = { 50 } >
// Very fast (data stream)
< TextTyping typingSpeed = { 20 } >
Cursor Customization
While the component uses a pipe character | by default, you can customize the appearance:
// Via CSS - target the cursor span
. typing - cursor {
color : #00 ff00 ;
font - weight : bold ;
}
Performance
Uses efficient setInterval for character updates
Automatic cleanup on unmount
Minimal re-renders
Framer Motion optimizes cursor animation
Very long text (1000+ characters) with fast typing speeds may impact performance. Consider breaking into multiple components.
Use Cases
Hero sections : Eye-catching headlines
Terminal interfaces : Code editor simulations
Chat bots : Realistic conversation flows
Loading states : Progress messages
Tutorials : Step-by-step instructions
Storytelling : Narrative reveals
Command prompts : CLI demonstrations
Notifications : System messages
Accessibility
Screen readers will announce the complete text
Final text is fully selectable
Animation completes, leaving readable content
Works with keyboard navigation
Consider providing a skip option for users sensitive to motion
Best Practices
Keep text concise for better impact (< 100 characters)
Match typing speed to content tone (slower for dramatic, faster for technical)
Ensure sufficient contrast for the cursor
Don’t overuse on a single page (1-2 instances maximum)
Provide static fallback for users with reduced motion preferences