Expiry
A time limit on an element — an "undo" button, an offer, a one-time link — with the element burning away as the time runs out. The element stays native; the time limit and what expiry means are yours.
Live: burn timer playground.
Usage
<button id="undo">Undo send · <span id="left">7</span>s</button>
import { createRenderer, createExpiryFx } from 'webgl-ui'
const renderer = createRenderer()
const undo = document.querySelector<HTMLButtonElement>('#undo')!
const expiry = createExpiryFx(undo, {
renderer,
seconds: 7,
onTick: s => { left.textContent = String(s) },
onExpire: () => { undo.hidden = true } // same task as the last frame: nothing flashes
})
expiry.start()
undo.addEventListener('click', () => { expiry.cancel(); undoSend() })
Options
| Option | Type | Default | Description |
|---|
renderer | Renderer | () => Renderer | required | The shared renderer. |
seconds | number | required | How long the element lives. |
effect | EffectDef | burnEffect | Receives uBox (the element in canvas pixels) and uDrift (the flames' clock). |
bleed | number | 56 | How far flames and smoke may reach outside the element, in CSS pixels. The element must not clip its overflow. |
onTick | (secondsLeft) => void | none | Each time the whole seconds left change: update your text. |
onExpire | () => void | none | When the time is up, in the same task as the last frame: hide, remove or replace the element. |
pauseOnInteraction | boolean | true | Pause while hovered or focused. |
Returns
| Member | Description |
|---|
start() | Starts the clock (and the burn). |
pause(), resume() | Stops and restarts the clock; while paused the burned state stays on screen, flames still. |
extend(seconds) | Adds time. |
cancel() | Stops for good without expiring (the action was taken); the element is shown intact. |
secondsLeft() | Whole seconds left. |
destroy() | Stops and removes the listeners. |
CSS hooks
| Hook | Meaning |
|---|
[data-animating], --p | While the burn runs; --p is the share burned. |
[data-paused] | While the clock is stopped (hover, focus or pause()). |
--fx-cover | The page colour behind the element, which the burned part is painted with. Default: the parent's background. |
Behavior and accessibility
- Time limits must be adjustable (WCAG 2.2.1): the clock stops while the element is hovered or focused, and
extend() adds time; offer a visible way to ask for more when the limit matters, and keep it generous.
- Motion that lasts more than five seconds must be stoppable (WCAG 2.2.2): pausing the clock also stills the flames.
- Announce the limit once and the outcome once (an
aria-live status), not every second.
- WebGL cannot read the page: the burned part is painted with
--fx-cover, so the element should sit on a flat background.
- Reduced motion, forced colors, more contrast, reduced transparency or no WebGL2: the timer runs the same, without fire.