ASCII revealPro
The image renders first as ASCII in Geist Mono, then each glyph cell dissolves into a pixel of the picture's own color, and the pixels resolve into the photo.
On this page
ProASCII in Geist Mono dissolving cell by cell into pixels, then the photo, at 48, 72 or 96 columns.
Installation
Usage
import { AsciiReveal } from "@/components/ui/chatcn/pro/ascii-reveal"
<AsciiReveal src={image.url} alt={image.prompt} columns={72} />Glyphs are matched by shape (edges read as / \ | _) from the shared glyph atlas and drawn once per size and theme. The dissolve is one draw per frame, so 96 columns stay smooth.
Examples
States
Waiting for the image, running at 40%, running with no numbers, held by revealed={false}, revealed, a missing file, a timer and right to left.
ProEvery state of the ASCII reveal.
Props
| Prop | Type | Notes |
|---|---|---|
src, alt | string | alt is required: the accessible name, announced once the image is in |
progress | number | null | Real job progress, 0 to 1. null means running with no numbers. Leave it out for timer mode |
revealed | boolean | Timer mode: false holds the first frame, true plays once the image loads. Default true |
duration | number | Timer length in ms. Default 2400 |
onRevealed | () => void | Once per image, when the plain image shows |
onStatusChange | (status: "loading" | "ready" | "revealing" | "revealed" | "error") => void | |
aspectRatio, width, height | Set the frame before the image loads, so nothing shifts | |
paper | string | The ground under the effect. Token or CSS color. Default var(--chatcn-bg) |
announcement | string | false | What the live region says once revealed. Default Image ready: <alt> |
errorText, retryLabel | Copy for the error state and its reload button | |
columns | number | Characters across. Default 64 |
mode | "shape" | "luminance" | Default shape |
order | "random" | "bayer" | "rows" | "diagonal" | "center" | Order the cells turn into pixels. Default random |
seed | number | Seeds the dissolve. Default 1 |
ink, contrast | Glyph color and contrast. Defaults var(--chatcn-fg) and 1.15 | |
maxPixels | number | Default 1.5 MP |
Keyboard
| Key | Action |
|---|---|
Tab | Reaches the Reload image button in the error state. The reveal itself takes no focus |
Accessibility
- The effect layer is
aria-hidden. The real<img>with youraltis always there, and the frame isaria-busyuntil the reveal ends. - A polite live region says
Image ready: <alt>once, when the plain image shows. Progress ticks are never announced. - Under
forced-colors: activethe effect hides and the plain image shows with system colors. - A broken file shows what happened and a Reload image button that retries the download.
Motion
- The ASCII holds for 18% of the run, cells flip to pixels over 57%, then the pixels crossfade to the photo. Cells flip, they never slide.
- Under reduced motion one still frame holds while the job runs, then the image crossfades in over 200 ms. Nothing moves.
- The timer only runs on screen in a visible tab; offscreen it waits where it was.