Installation
pnpm dlx shadcn@latest add https://asciicn.dev/r/ascii-donut.jsonUsage
import { AsciiDonut } from "@/components/asciicn/ascii-donut";
export function Spinner() {
return <AsciiDonut className="aspect-square w-80" />;
}Every sample casts a ray from a perspective camera and marches it into the torus, so the silhouette, the hole and the near side overlapping the far side are exact at any cell size. Braille and quadrants sample 2×4 and 2×2 times per cell, which sharpens the outline further.
The shading is built for glyphs. A key light sets the body tone, a cool rim light from behind outlines the far edge, the inside of the ring sits in soft shadow, and a tight specular highlight is the only place the densest glyphs appear. In truecolor, the body takes color, the rim takes rim, and highlights go white.
At rest the ring leans toward you in a three-quarter view, with the hole open, and rocks slowly a little either way while it turns on its own axis. It never turns edge-on by itself, and it does not react to hover.
Press and drag to turn it. Let go mid-drag and it coasts, then eases back to its resting view. With keyboard focus, the arrow keys turn it.
Examples
Ribbed, in Braille
surface="ribbed" winds grooves around the tube, which catch the light as the ring turns on its axis.
CP437 on a green phosphor
Mono with the P1 phosphor and a CRT finish from fx.
Props
Every ASCII image look prop also applies, with charset defaulting to "standard", plus fx for a CRT finish.
| Prop | Type | Default |
|---|---|---|
| radius Ring radius as a share of half the box's shorter side. | Type: number | Default 0.5 |
| thickness Tube radius over ring radius, 0.1 to 0.9. | Type: number | Default 0.46 |
| spin Turn around the ring's own axis, in radians per second. Shows on the ribbed surface. | Type: number | Default 0.4 |
| speed Multiplies the spin and the slow rocking. 0 holds it still until dragged. | Type: number | Default 1 |
| surface A plain ring, or grooves wound around the tube. | Type: "smooth" | "ribbed" | Default "smooth" |
| color Body colour in truecolor. | Type: AsciiColor | Default "orange" |
| rim Rim light colour in truecolor. | Type: AsciiColor | Default "blue" |
| light Where the key light comes from, in degrees clockwise from the top. | Type: number | Default 315 |
| floor A soft shadow on an unseen floor below the ring. | Type: boolean | Default true |
| colorMode How glyphs are coloured. | Type: "mono" | "truecolor" | "ansi16" | "duotone" | "palette" | Default "truecolor" |
| draggable Drag or use the arrow keys to turn it. | Type: boolean | Default true |
| cell Glyph cell height in CSS pixels. | Type: number | Default 10 |
| animate false draws one still frame. | Type: boolean | Default true |
| handle Filled with a handle for export. | Type: RefObject<AsciiHandle | null> | Default – |
Notes
- It is announced as an image. Pass
aria-labelto describe what it stands for on your page. - Under reduced motion it draws one still frame, in the resting three-quarter view.
- Only a press and drag turns it. Moving the mouse over it changes nothing.
- It draws at up to 60 fps and pauses offscreen and in hidden tabs. Rays that miss the ring's bounding sphere skip the march, so empty space costs almost nothing.