Docs
Go back
Component by
OV
OblivionOBLIVION UI IS NEXT GEN.
Hover to decrypt
TSX
text-scramble
"use client"
import { useEffect, useState, useRef } from "react"
import { motion, useInView } from "framer-motion"
export const componentMeta = {
name: "Text Scramble",
description: "A hacker-style decrypting text reveal animation that triggers on hover or scroll.",
props: {
text: { type: "string", default: "Oblivion UI is the future.", description: "Text to scramble and reveal" },
speed: { type: "number", default: "50", description: "Speed of decryption in ms" }
}
}
const CHARS = "!<>-_\\/[]{}—=+*^?#________"
export default function TextScramble({
text = "OBLIVION UI IS NEXT GEN.",
speed = 50
}: {
text?: string
speed?: number
}) {
const [displayText, setDisplayText] = useState(text)
const isMounted = useRef(false)
const scramble = () => {
let pos = 0
const interval = setInterval(() => {
setDisplayText(prev => {
const scrambled = text.split("").map((char, index) => {
if (pos >= text.length) {
clearInterval(interval)
return text[index]
}
if (index < pos) return text[index]
if (char === " ") return " "
return CHARS[Math.floor(Math.random() * CHARS.length)]
})
return scrambled.join("")
})
pos += 1 / 3 // Reveal slowly
}, speed)
}
useEffect(() => {
if (!isMounted.current) {
scramble()
isMounted.current = true
}
}, [])
return (
<motion.div
onMouseEnter={() => scramble()}
className="group relative cursor-crosshair w-full max-w-2xl mx-auto text-center px-4"
>
<h2 className="text-4xl md:text-5xl font-mono font-bold text-neutral-900 dark:text-white tracking-tight break-words">
{displayText}
</h2>
<p className="text-sm text-neutral-400 mt-4 uppercase tracking-widest font-sans opacity-0 group-hover:opacity-100 transition-opacity">
Hover to decrypt
</p>
</motion.div>
)
}"use client"
import { useEffect, useState, useRef } from "react"
import { motion, useInView } from "framer-motion"
export const componentMeta = {
name: "Text Scramble",
description: "A hacker-style decrypting text reveal animation that triggers on hover or scroll.",
props: {
text: { type: "string", default: "Oblivion UI is the future.", description: "Text to scramble and reveal" },
speed: { type: "number", default: "50", description: "Speed of decryption in ms" }
}
}
const CHARS = "!<>-_\\/[]{}—=+*^?#________"
export default function TextScramble({
text = "OBLIVION UI IS NEXT GEN.",
speed = 50
}: {
text?: string
speed?: number
}) {
const [displayText, setDisplayText] = useState(text)
const isMounted = useRef(false)
const scramble = () => {
let pos = 0
const interval = setInterval(() => {
setDisplayText(prev => {
const scrambled = text.split("").map((char, index) => {
if (pos >= text.length) {
clearInterval(interval)
return text[index]
}
if (index < pos) return text[index]
if (char === " ") return " "
return CHARS[Math.floor(Math.random() * CHARS.length)]
})
return scrambled.join("")
})
pos += 1 / 3 // Reveal slowly
}, speed)
}
useEffect(() => {
if (!isMounted.current) {
scramble()
isMounted.current = true
}
}, [])
return (
<motion.div
onMouseEnter={() => scramble()}
className="group relative cursor-crosshair w-full max-w-2xl mx-auto text-center px-4"
>
<h2 className="text-4xl md:text-5xl font-mono font-bold text-neutral-900 dark:text-white tracking-tight break-words">
{displayText}
</h2>
<p className="text-sm text-neutral-400 mt-4 uppercase tracking-widest font-sans opacity-0 group-hover:opacity-100 transition-opacity">
Hover to decrypt
</p>
</motion.div>
)
}Save to favoritesCopy to Figma
React
Text Scramble
A hacker-style decrypting text reveal animation that triggers on hover or scroll.
Installation
$ npx @cosmoo/oblivion add text-scrambleDependencies
npm install framer-motionUsage Example
tsx
import TextScramble from "@/components/oblivion/text-scramble"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<TextScramble />
</div>
)
}import TextScramble from "@/components/oblivion/text-scramble"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<TextScramble />
</div>
)
}