KQ-1380 · DATAMOSH/TYPE
Datamosh Type
A headline that fails the way compressed video fails: between bursts it is plain, selectable DOM text, and a burst swaps it for a canvas picture of the same glyphs that is corrupted frame by frame at a codec's frame rate — grid-aligned rows of macro-blocks slip sideways and drag a pixel run behind them, blocks freeze on the previous frame, drift to another block's pixels or quantise into a mosaic, and the two colour channels split apart behind the ink. Each burst ramps in, holds and decays on its own envelope rather than a spring, then a clean key frame puts the real text back in one frame. Bursts come on an interval while on screen, on pointer entry (clustered where the pointer came in), a tap, keyboard focus on the headline (a tab stop by default) or the link around it, and each change of burstKey.
Fernworks Studio · Reel 04
Every frame survives the cutFocus plays the corruption; with reduced motion it shows the clean text.
burst 0 · clean frame
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/datamosh-type
Props
- children
- string
- default —
- The headline; it stays real, selectable text between bursts.
- as
- "span" | "div" | "p" | "h1" | "h2" | "h3" | "h4"
- default "span"
- The root element.
- intensity
- number
- default 0.6
- How many artefacts a burst throws and how far they shift, 0 to 1.
- burst
- number
- default 520
- Length of one burst, ms.
- split
- number
- default 0.04
- How far apart the two colour channels drift, em.
- block
- number
- default 0.28
- The macro-block size, em.
- smear
- number
- default 0.5
- How often and how far a pixel run drags behind a slipped row, 0 to 1.
- freeze
- number
- default 0.5
- The share of corrupted blocks that hold a stale frame, 0 to 1.
- fps
- number
- default 24
- The codec's frame rate inside a burst, 8 to 60.
- interval
- number
- default 3600
- Rest between automatic bursts, ms; 0 turns them off.
- channels
- [string, string]
- default ["var(--danger)", "var(--accent-bright)"]
- The two channel colours, any CSS colour; tokens follow the theme.
- hover
- boolean
- default true
- Pointer entry, a tap and keyboard focus each fire a burst.
- focusable
- boolean
- default true
- A tab stop of its own, so the keyboard can fire a burst or, under reduced motion, clear the still frame; turn off inside a link or button, which is focused instead.
- trigger
- "mount" | "inView" | "hover" | "manual"
- default "inView"
- When automatic bursts run; hover and manual turn the interval off.
- once
- boolean
- default false
- One automatic burst, then rest.
- delay
- number
- default 400
- Wait before the first automatic burst, ms.
- burstKey
- string | number
- default —
- Each change fires one burst: the host's own trigger.
- seed
- number
- default 7
- Seeds every burst's corruption, so a page breaks the same way each visit.
- paused
- boolean
- default false
- No bursts at all; one under way ends clean.
- dpr
- number
- default 2
- The most device pixels per CSS pixel the canvas may use, capped at 2.
- onBurstStart
- () => void
- default —
- A burst began.
- onComplete
- () => void
- default —
- A burst ended on a clean key frame.
- className
- string
- default —
- Classes for the root; the canvas copies its font and colour.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | string | — | The headline; it stays real, selectable text between bursts. |
| as | "span" | "div" | "p" | "h1" | "h2" | "h3" | "h4" | "span" | The root element. |
| intensity | number | 0.6 | How many artefacts a burst throws and how far they shift, 0 to 1. |
| burst | number | 520 | Length of one burst, ms. |
| split | number | 0.04 | How far apart the two colour channels drift, em. |
| block | number | 0.28 | The macro-block size, em. |
| smear | number | 0.5 | How often and how far a pixel run drags behind a slipped row, 0 to 1. |
| freeze | number | 0.5 | The share of corrupted blocks that hold a stale frame, 0 to 1. |
| fps | number | 24 | The codec's frame rate inside a burst, 8 to 60. |
| interval | number | 3600 | Rest between automatic bursts, ms; 0 turns them off. |
| channels | [string, string] | ["var(--danger)", "var(--accent-bright)"] | The two channel colours, any CSS colour; tokens follow the theme. |
| hover | boolean | true | Pointer entry, a tap and keyboard focus each fire a burst. |
| focusable | boolean | true | A tab stop of its own, so the keyboard can fire a burst or, under reduced motion, clear the still frame; turn off inside a link or button, which is focused instead. |
| trigger | "mount" | "inView" | "hover" | "manual" | "inView" | When automatic bursts run; hover and manual turn the interval off. |
| once | boolean | false | One automatic burst, then rest. |
| delay | number | 400 | Wait before the first automatic burst, ms. |
| burstKey | string | number | — | Each change fires one burst: the host's own trigger. |
| seed | number | 7 | Seeds every burst's corruption, so a page breaks the same way each visit. |
| paused | boolean | false | No bursts at all; one under way ends clean. |
| dpr | number | 2 | The most device pixels per CSS pixel the canvas may use, capped at 2. |
| onBurstStart | () => void | — | A burst began. |
| onComplete | () => void | — | A burst ended on a clean key frame. |
| className | string | — | Classes for the root; the canvas copies its font and colour. |