Add this component

npx zentauri-ui add decrypted-text

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Typography & motion

From noise to words.

Text that cycles through random glyphs and settles into the real string, letter by letter. The line never shifts, and assistive tech always reads the real words.

Secure channel / 003

Access granted to the mainframe

Each letter cycles through random glyphs before it lands. The line never changes width, and screen readers hear the real text.

Your decoder

Tune the signal.

Use the page theme toggle to compare light and dark.


Access granted to the mainframe

Iterations apply to the together order.

Choose the colour of scrambled glyphs. Hover or focus a card to preview it.

default
muted
matrix
cyan
amber
violet
rose

Same text. Different signal.

Choose where letters start resolving, which glyphs they cycle through, and how each one lands. Every example decodes when it scrolls into view.

Decodes from the start once it scrolls into view


Access granted to the mainframe

Resolves from the centre and flips each letter into place


Signal acquired

Binary noise that resolves all at once


Handshake complete

Faint glyphs brighten into letters in a random order


Quietly revealing the plan

Noise for the eyes. Words for everyone else.

The real text sits in a visually hidden copy, and the animated letters are hidden from assistive tech, so screen readers never hear the noise. With reduced motion or with scripts off, the final text shows straight away.

A scrambled glyph floats over its hidden real letter and is squeezed to that letter's width, so the line never reflows while it decodes. Resolved letters stay inline and keep the font's kerning.

One animation loop advances a step every speed milliseconds and only touches the letters that changed, with no React render per step. With trigger hover, keyboard focus also starts decoding, and inside a link or button the text follows that control's hover and focus.

Decrypted Text API

Generated from the package prop types and variant definitions.

DecryptedText

DecryptedTextProps

Variants

PropTypeDefault
appearance
ambercyandefaultmatrixmutedroseviolet
default

Behavior

PropTypeDefault
asElement to render.DecryptedTextElement | undefined"span"
charactersPool of glyphs used while scrambling.string | undefinednone
delayDelay before decoding starts, in milliseconds. Clamped to 0–10000.number | undefined0
effectHow each letter lands.DecryptedTextEffect | undefined"scramble"
iterationsScramble steps before every letter resolves with `order="together"`. Clamped to 1–100.number | undefined10
onCompleteCalled each time decoding finishes, or immediately when motion is reduced.(() => void) | undefinednone
orderWhich letters resolve first.DecryptedTextOrder | undefined"start"
speedTime between steps in milliseconds. Clamped to 16–1000.number | undefined50
triggerWhen decoding starts.DecryptedTextTrigger | undefined"view"
useOriginalCharsScramble with only the letters that appear in the text.boolean | undefinedfalse

Content

PropTypeDefault
children*The text to decode. Assistive tech always reads it as plain text.stringnone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLSpanElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

DecryptedTextVariant

DecryptedTextVariantProps

Behavior

PropTypeDefault
appearance'default' | 'cyan' | 'rose' | 'violet' | 'amber' | 'muted' | 'matrix' | null | undefinednone
CSS variable overrides

Decrypted Text CSS variables

Colour the glyphs shown while each letter is still scrambled. Timing and order are configured through props; private --_dt-* values are not a public token API.

14 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-decrypted-text-glyph: currentColor;
  --zui-decrypted-text-muted-glyph: #64748b;
  --zui-decrypted-text-matrix-glyph: #15803d;
  --zui-decrypted-text-cyan-glyph: #0e7490;
  --zui-decrypted-text-amber-glyph: #b45309;
  --zui-decrypted-text-violet-glyph: #6d28d9;
  --zui-decrypted-text-rose-glyph: #be123c;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-decrypted-text-glyph-dark: currentColor;
  --zui-decrypted-text-muted-glyph-dark: #94a3b8;
  /* ...same variables with -dark at the end */
}

Overview

Import DecryptedText from the decrypted-text entry and pass the text as a string child. It renders a span by default; set as to render a p, div, or heading. The defaults are trigger view, order start, effect scramble, speed 50 ms, iterations 10, delay 0, and appearance default, which keeps the surrounding text colour for scrambled glyphs.

The view and mount triggers start scrambled, and the first glyphs are deterministic so server and client HTML match. The hover trigger starts as plain text and also responds to keyboard focus. onComplete fires each time decoding finishes. Style letters that are still scrambled with the [data-scrambled] attribute.

Consumers using Tailwind v4 must include the package in their @source scan so both light and dark token classes are generated.

Common use cases

  • Hero headlines and section labels with a technical or security theme.
  • Link and button labels that decode on hover or keyboard focus.
  • Status lines such as "Connection established" in dashboards and terminals.

FAQ

Do screen readers hear the random characters?

No. The real text is kept in a visually hidden copy and the animated letters are aria-hidden, so assistive tech reads the final words from the start.

Does the text jump around while it decodes?

No. Each scrambled glyph floats over its hidden real letter and is squeezed to that letter's width, so the line keeps its width throughout.

Does it need Framer Motion?

No. It runs on one requestAnimationFrame loop and writes to the letters directly. The flip effect uses the browser's Web Animations API.