Media & effects
Text Scramble Decoder
Controlled technical typography reveal
detent-text-scramble-decoder
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 4
- Wave
- phase-4-canvas
- Group
- Media & effects
4.2 KB gzip for the class module
Variants
The readable text never changes: only the decorative glyph layer is scrambled, and it is
aria-hidden, so the copy is read once. Each run resolves position by position; a second hover, a
property write or a replayed decode cancels the run in flight instead of stacking. With
prefers-reduced-motion: reduce the final text is written immediately and no frame is scheduled.
trigger="hover" — move the pointer over the line
trigger="manual" — replay button, disabled while decoding
custom glyph alphabet and a 500 ms run
Documented parts: root, text, glyph, replay,
replay-icon. Documented custom properties: --detent-scramble-text,
--detent-scramble-glyph, --detent-scramble-surface, --detent-scramble-radius,
--detent-scramble-font-size, --detent-scramble-replay-bg,
--detent-scramble-replay-border, --detent-scramble-replay-icon.
Recorded states
reduced motionrecorded state; no setter
Usage
Import
import '/components/text-scramble-decoder/define.js';
// or register it yourself
import { DetentTextScrambleDecoder } from '/components/text-scramble-decoder/text-scramble-decoder.js';
Attributes
charactersdurationreplay-labeltexttrigger
Properties
No properties are recorded for this component.
Slots
No slots are recorded for this component.
Events
No events are recorded for this component.
Example
Runnable example: site/examples/text-scramble-decoder.ts. The snippet below is generated from the catalogued attributes.
<detent-text-scramble-decoder
characters
duration="900"
replay-label
text
trigger="mount"
></detent-text-scramble-decoder>
Source
The pinned upstream source for this row:
src/components/ui/TextScrambleDecoder.tsxsha256 5e7cb5af556d…
Native files
The native module and its artifacts:
src/components/text-scramble-decoder/text-scramble-decoder.tssrc/components/text-scramble-decoder/styles.csssrc/components/text-scramble-decoder/define.tsdocs/components/text-scramble-decoder.mdsite/examples/text-scramble-decoder.tstests/browser/text-scramble-decoder.spec.tsevidence/components/text-scramble-decoder.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
characters | characters | string | A-Z, 0-9, symbols | Kebab-case attribute; camelCase property. |
duration | duration | number | 900 | Kebab-case attribute; camelCase property. |
replay-label | — | — | — | Recorded in the catalog as an attribute. |
text | text | string | — | Kebab-case attribute; camelCase property. |
trigger | trigger | 'mount' | 'hover' | 'manual' | 'mount' | Kebab-case attribute; camelCase property. |
Properties
No property-only values are recorded for this component.
Events
No custom events are recorded for this component.
Slots
No slots are recorded for this component.
CSS customisation
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- duration clamps to 0..20000 ms and blank characters fall back to the pinned alphabet; a negative duration made the source loop forever.
- Progress and cadence are measured from the run first frame instead of performance.now().
- Progress 0 is painted synchronously at run start, so there is no flash of the final text.
- lucide-react RefreshCw becomes a local SVG (the ISC notice is already in THIRD_PARTY_NOTICES.md).
- Colours are theme tokens with light/dark hex fallbacks, and the replay border and icon are raised above the pinned #1F1F1F/#525252 (2.4:1) to at least 4.5:1.
- The accessible reading is real text in a visually hidden span as well as the pinned aria-label, because a generic span aria-label alone is not exposed by any of the three engines.
- The catalog records duration 900 while the pinned source initialises 800; the row is the API authority, so the native default is 900. Owner confirmed 900 on 2026-10-29.
What it does
A controlled technical typography reveal: scrambled glyphs resolve position by position into readable text. The readable text never changes — only the painted glyph layer does — so the copy stays one reading for assistive technology.
Upstream behaviour
- Position-staged character resolution with a stable final state
- Mount, hover, and manual replay trigger modes
- Configurable glyph set and duration
Differences from upstream
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- duration clamps to 0..20000 ms and blank characters fall back to the pinned alphabet; a negative duration made the source loop forever.
- Progress and cadence are measured from the run first frame instead of performance.now().
- Progress 0 is painted synchronously at run start, so there is no flash of the final text.
- lucide-react RefreshCw becomes a local SVG (the ISC notice is already in THIRD_PARTY_NOTICES.md).
- Colours are theme tokens with light/dark hex fallbacks, and the replay border and icon are raised above the pinned #1F1F1F/#525252 (2.4:1) to at least 4.5:1.
- The accessible reading is real text in a visually hidden span as well as the pinned aria-label, because a generic span aria-label alone is not exposed by any of the three engines.
- The catalog records duration 900 while the pinned source initialises 800; the row is the API authority, so the native default is 900. Owner confirmed 900 on 2026-10-29.