Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Decrypted Text for React

Text that decrypts itself, each character running through scrambled glyphs before it settles. For React with Base UI, when a label should feel like it's being decoded.

Framework

Decrypted Text scrambles each character through a run of random-looking glyphs before it settles on the real one, one after another, as if the text were being decoded. By default it plays whenever the pointer is over it; it can also play once when it scrolls into view, or as soon as the page shows it.

Use it for a short label with a technical feel: a status, a code name, a heading on a security or developer page. For noise that never settles, use Glitch Text; for zeros and ones, Binary Text. There's no timer and nothing random: every character is a window over a column of glyphs, stepped through by a CSS keyframe animation the install adds to your stylesheet, so the server and the browser draw the same glyphs. With reduced motion the text is plain.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { DecryptedText } from "@/components/ui/decrypted-text";
<DecryptedText text="Hover to decrypt" />

Demos

View

trigger="view" scrambles the text from the start and decrypts it once it scrolls into view; revealFrom is where it settles first: start, end, or center, outward.

Preview width

Characters

characters is what the scramble draws from: 01 for binary, katakana for a film's terminal, symbols for a password. trigger="mount" plays it as soon as the page shows it.

Preview width

Timing

steps is how many glyphs each character runs through, speed how long each shows, and stagger the time between one character settling and the next; stagger={0} settles them all at once.

Preview width

Accessibility

Screen readers read the real text once, from a visually hidden copy, never the scrambled glyphs. Every character keeps its own width while it scrambles, so the line never shifts. With reduced motion the text shows as it is.

FAQ

Are the scrambled glyphs random?

They look random but aren't: each glyph is picked from characters by a small formula of the character's place and the step, so the server and the browser draw the same ones and the page never mismatches.

Does it play again on every hover?

Yes, with trigger="hover", the default: each time the pointer comes over the text it scrambles and decrypts again. On a touch screen, where there's no hover, it shows the text.

Why doesn't the line jump while it scrambles?

Each character is a window as wide as the real character, with the glyphs in a column behind it: a wider glyph is clipped, never pushed against its neighbours.

Which font suits it?

Any, but a monospaced font, such as font-mono, keeps every glyph the same width, so the scramble reads as one even block.

What does it show without JavaScript?

With trigger="view", the decrypted text, since nothing would start the animation. The other triggers are CSS alone and play as usual.

What happens with reduced motion?

The text shows as it is, with no scramble.

API Reference

DecryptedText

<span> data-slot="decrypted-text"

PropType
textstring

The text.

characters?string

The characters the scramble draws from. Ark default: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+.

Default
CHARACTERS
revealFrom?"start" | "end" | "center"

Where the text settles first: its start, its end, or its middle. @default "start".

Type
"start" | "end" | "center"
Default
"start"
speed?number

How long each scrambled character shows, in milliseconds. @default 50.

stagger?number

The time between one character settling and the next, in milliseconds; 0 settles them all at once.

Default
40
steps?number

How many scrambled characters each one runs through. @default 10.

Default
10
trigger?"hover" | "view" | "mount"

What plays it: the pointer over the text (again on every hover), the text scrolling into view, or the page showing it.

Type
"hover" | "view" | "mount"
Default
"hover"
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

AttributeType
data-view?string

"in" when visible is true, otherwise "out".

CSS variableType
--decrypted-text-speedstring

How long each scrambled character shows (50ms).

--decrypted-text-staggerstring

The time between one character settling and the next (40ms).

--decrypted-text-stepsstring
All 97 text effects