import { Component } from '@angular/core';
import { WrDecode } from 'ngwr/animations/decode';
@Component({ imports: [WrDecode] })
export class MyComponent {}Decode
A readout locking on: every character shows random glyphs that change quickly, then settles on the real one, left to right. The line never moves while it plays.
Installation
Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.
Basic
Put wrDecode on the element that holds the text. By default it plays once, when most of the element is in view. A glyph keeps the shape of the character it stands in for, so the word shape stays readable, and spaces never scramble.
<wr-tag color="primary" outlined><span wrDecode>Developer experience</span></wr-tag>
<h2 wrDecode>Release 15.7 is out.</h2>Hover
trigger="hover" plays on every pointer enter and on focus, of the element or of its closest focusable ancestor, so a label inside a button decodes when the button is reached by keyboard too. A play in progress is never restarted.
<button wr-btn outlined type="button"><span wrDecode trigger="hover">Hover or focus me</span></button>Glyphs
glyphs is the set every slot draws from, instead of the shape of its own character: binary for a readout, a few symbols for a glitch.
<p wrDecode glyphs="01">Resolved in 2.4 ms</p>Timing
delay is the pause between the trigger and the first glyph; the text stands as authored meanwhile. stagger is the gap between one slot locking and the next, 36 ms unset, and the locks spread over 1.2 s at most. The colour a glyph paints in before it locks is --wr-decode-tint, mixed from the text's own colour.
<p wrDecode delay="400" stagger="80">Slow enough to watch each slot lock.</p>.readout {
--wr-decode-tint: color-mix(in srgb, var(--wr-color-primary) 50%, transparent);
}Accessibility
| Part | Behaviour |
|---|---|
| Screen readers | While the slots play they are aria-hidden, and a visually hidden copy of the text stands beside them, so the text is announced once and the noise never. At rest the element holds its original text nodes. |
| Reduced motion | Under prefers-reduced-motion: reduce nothing plays, in either trigger mode: the text is shown as authored. The demos on this page follow the same setting. |
| Keyboard | In hover mode focus plays it too, read on the closest focusable ancestor, so a label inside a button or a link behaves the same for a pointer and for Tab. |
| Layout | The real character stays in its slot, hidden, and the glyph is painted over it out of flow, so the line keeps its width and nothing around it moves. |
| Server | The server renders the plain text. The slots are created in the browser, after the first render, and in view mode only where IntersectionObserver exists. |
API
| Name | Description | Type | Default |
|---|---|---|---|
trigger | view plays once, the first time most of the host is in the viewport. hover plays on every pointer enter and focus of the host or its closest focusable ancestor, but never restarts while already playing. | WrDecodeTrigger | 'view' |
glyphs | The characters random glyphs are drawn from, for every slot. Unset, each slot draws from the shape of its own character: uppercase letters and digits for an uppercase letter, lowercase for lowercase, digits for a digit, a few symbols for anything else. | string | null | null |
stagger | Gap between one slot locking and the next, in ms. Unset, 36. Either way the locks spread over 1.2 s at most, so for a long text the gap shrinks until the last slot locks by then. | number | null | null |
delay | Pause between the trigger and the first glyph, in ms. The text stands as authored meanwhile. | number | 0 |
CSS variables
Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/animations/decode declares each default on its own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-decode-ease | var(--wr-ease-out) | .wr-decode |
--wr-decode-settle | 240ms | .wr-decode and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes |
--wr-decode-tint | color-mix(in srgb, currentColor 45%, transparent) | .wr-decode |
See also
Animation Blur RevealA text comes in piece by piece the first time it scrolls into view: each word, or each letter, from blurred and a little below its place to sharp and in place.Animation ShimmerA soft band of light crosses the glyphs of a short label, waits, and crosses again for as long as the label is on screen.Guide MotionEasing and duration tokens for your transitions and animations.Component BadgeA small label for a count or a status.