Cipher Text
textProText that decodes out of glitch characters in five orders (left-to-right, right-to-left, random, centre, per line), with optional flicker, viewport trigger and replay, plus diffuse and wave hover modes that never shift the layout.
Pro cannot be bought yet. The page opens when payment is ready.
Preview
Live demo. The theme switches the demo itself.
Code
The code is locked
Cipher Text is part of Manniche UI Pro. A key unlocks the source of all 60 effects.
Opening soon€49 · Introductory price until 31 December 2026. €79 after that.
- One-off payment
- One developer
- Your key arrives by email straight away
- No VAT (§ 19 UStG)
Have a key? Get the code with the CLI or MCP.
The key lives in MANNICHE_PRO_KEY, never in your code or a URL. How to set it up
npx shadcn@latest add @manniche-pro/cipher-textclaude mcp add --transport http manniche-ui https://mikkelmanniche.dk/api/mcp --header "Authorization: Bearer $MANNICHE_PRO_KEY"Props
CipherTextProps
| Prop | Type | Default | What it does |
|---|---|---|---|
text required | string | – | The text. Use \n for line breaks (needed for mode="lines"). |
as | ElementType | 'span' | The element to render, e.g. h1, p or span. |
mode | CipherTextMode | 'ltr' | The order the letters decode in: ltr and rtl sweep along the text, random picks letters in a shuffled order, center opens from the middle, lines decodes each line as a unit, one line after the other. |
hover | CipherTextHover | 'none' | What the pointer does once the text has decoded: diffuse re-scrambles the letters around the pointer and lets them settle again, wave sends a ring of scrambling letters rippling out from where you touch. |
charset | CipherSetName | (string & {}) | 'glyphs' | Glitch characters: a preset name (glyphs, symbols, binary, blocks, katakana, hex) or your own string. |
duration | number | 1400 | Length of the whole reveal in milliseconds, from the first letter starting to the last one settling. |
delay | number | 0 | Wait before the reveal starts, in milliseconds. |
settle | number | 650 | How long each letter stays scrambled before it locks in, in milliseconds. |
ease | CipherEase | 'out' | Easing of the order in which letters start: linear, in, out or inOut. |
prefill | boolean | false | When true, letters show glitch characters from the start instead of staying blank until their turn. |
swapEvery | number | 55 | Milliseconds between glyph changes of one scrambling letter. Lower is more frantic. |
trigger | 'view' | 'mount' | 'view' | view starts when the text scrolls into view, mount starts at once. |
once | boolean | true | With trigger="view": play only the first time (true) or every time it re-enters the screen (false). |
threshold | number | 0.35 | Share of the text that has to be visible before trigger="view" fires, 0 to 1. |
replayKey | string | number | – | Change this value to replay the reveal, e.g. increase a counter from a button. |
replayOnClick | boolean | false | Replay when the text is clicked or tapped (mouse and touch only; offer a real button for keyboard users). |
flicker | boolean | false | Adds a flicker: scrambling letters stutter in brightness and flash in flickerColor as they lock in. |
flickerColor | string | – | Colour of the flicker flashes. Defaults to the glitch colour. |
glitchColor | string | – | Colour of scrambling letters. Defaults to the text colour (currentColor). |
glitchOpacity | number | 0.6 | Opacity of scrambling letters, 0 to 1. |
hoverRadius | number | 90 | Reach of diffuse, in pixels from the pointer. |
hoverSettle | number | 520 | How long diffuse letters take to settle again, in milliseconds. |
waveSpeed | number | 0.55 | Travel speed of wave, in pixels per millisecond. |
waveWidth | number | 70 | Thickness of the wave ring, in pixels. |
onRevealed | () => void | – | Called once when a reveal has fully settled. |
className | string | – | Classes for the element. |
style | CSSProperties | – | Inline style for the element. |
A11y
Screen reader
The real text sits once in a visually hidden span and is read as plain text. The scrambling glyph layer is aria-hidden, so the glitch characters are never announced and nothing changes for screen readers during the reveal. The heading level follows as.
Reduced motion
Under reduced motion the text is shown fully at once and onRevealed fires immediately. Otherwise the reveal starts when it scrolls into view (trigger="view") or on mount, and the hover scramble reacts only to the pointer and settles back on its own.
Other
replayOnClick works with mouse and touch only and gives no tab stop. Offer a real button, wired to replayKey, for keyboard users.