Text Scramble
The TextScramble component creates a captivating scramble animation effect where random characters rapidly cycle before resolving to the target text. Perfect for attention-grabbing headings, tech-themed interfaces, and dynamic content reveals.
Installation
npm install @craftdotui/components
Import
import TextScramble from "@craftdotui/components" ;
Usage
Basic Usage
Custom Speed and Duration
Trigger on Demand
Custom Character Set
import TextScramble from "@craftdotui/components" ;
export default function Example () {
return (
< TextScramble >
Hello, World!
</ TextScramble >
);
}
Props
The final text to display after the scramble animation completes.
Animation speed in milliseconds between character updates. Lower values = faster scrambling.
Total duration of the scramble animation in seconds.
Whether to trigger the animation. Set to false to show final text without animation.
Additional CSS classes. Component uses font-mono by default.
Custom set of characters to use during scrambling.
as
React.ElementType
default: "'span'"
HTML element type to render (span, div, h1, etc.).
Callback function fired when scramble animation completes.
Animation Details
Algorithm
The component uses a progressive reveal algorithm:
Starts with all characters scrambled
Progressively reveals characters from left to right
Characters to the left of currentIndex are finalized
Characters to the right continue scrambling
Spaces are preserved throughout
const scrambled = children
. split ( "" )
. map (( char , index ) => {
if ( char === " " ) return " " ;
return index < currentIndex
? char
: characterSet [ Math . floor ( Math . random () * characterSet . length )];
})
. join ( "" );
Timing
The animation interval runs at the specified speed, incrementing the reveal index:
setInterval (() => {
// Update scrambled text
currentIndex = Math . min ( currentIndex + 1 , children . length );
}, speed );
The animation automatically cleans up intervals on unmount to prevent memory leaks.
Examples
Hero Heading
import TextScramble from "@craftdotui/components" ;
export default function Hero () {
return (
< div className = "min-h-screen flex items-center justify-center bg-black" >
< TextScramble
as = "h1"
className = "text-6xl font-bold text-green-400"
speed = { 40 }
duration = { 2.5 }
>
SYSTEM ACCESS GRANTED
</ TextScramble >
</ div >
);
}
Matrix-Style Effect
import TextScramble from "@craftdotui/components" ;
export default function MatrixText () {
return (
< TextScramble
characterSet = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン01234567890"
className = "text-green-400 text-2xl bg-black p-4"
speed = { 25 }
duration = { 4 }
>
Wake up, Neo
</ TextScramble >
);
}
Sequential Reveals
import { useState , useEffect } from "react" ;
import TextScramble from "@craftdotui/components" ;
export default function SequentialReveal () {
const [ step , setStep ] = useState ( 0 );
const messages = [
"Initializing system..." ,
"Loading modules..." ,
"System ready." ,
];
return (
< div className = "space-y-4" >
{ messages . map (( msg , i ) => (
< TextScramble
key = { i }
trigger = { step >= i }
speed = { 30 }
duration = { 1.5 }
onScrambleEnd = { () => setStep ( i + 1 ) }
className = "text-xl text-cyan-400"
>
{ msg }
</ TextScramble >
)) }
</ div >
);
}
Interactive Button
import { useState } from "react" ;
import TextScramble from "@craftdotui/components" ;
export default function ScrambleButton () {
const [ isHovered , setIsHovered ] = useState ( false );
return (
< button
onMouseEnter = { () => setIsHovered ( true ) }
onMouseLeave = { () => setIsHovered ( false ) }
className = "px-8 py-4 bg-purple-600 text-white rounded-lg font-mono"
>
< TextScramble
trigger = { isHovered }
speed = { 20 }
duration = { 0.8 }
>
LAUNCH MISSION
</ TextScramble >
</ button >
);
}
Loading State
import TextScramble from "@craftdotui/components" ;
export default function LoadingState ({ isLoading }) {
return (
< div className = "flex items-center gap-3" >
< div className = "w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
< TextScramble
trigger = { isLoading }
speed = { 50 }
duration = { 2 }
className = "text-white"
>
Processing data
</ TextScramble >
</ div >
);
}
Combine with monospace fonts (font-mono) for the most authentic terminal/hacker aesthetic.
Character Set Examples
// Default (alphanumeric)
characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
// Binary only
characterSet = "01"
// Hexadecimal
characterSet = "0123456789ABCDEF"
// Symbols
characterSet = "!@#$%^&*()_+-=[]{}|;:,.<>?"
// Unicode blocks
characterSet = "█▓▒░"
// Katakana (Matrix style)
characterSet = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン"
Performance Considerations
Uses setInterval for character updates
Automatically cleans up on unmount
Minimal re-renders (only when scrambled text changes)
Lightweight algorithm with O(n) complexity
Using very low speed values (< 10ms) may cause performance issues on slower devices.
Use Cases
Tech/cyberpunk themed websites
Loading states with personality
Hero section headings
Terminal/CLI interfaces
Gaming UIs
Data visualization reveals
Countdown timers
Easter eggs and hidden messages
Accessibility
Final text is always readable
Screen readers will announce the final text
Animation can be disabled with trigger={false}
Consider reduced motion preferences for sensitive users