For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. The asciicn agent skill, for building any ASCII effect on the engine, is at /.well-known/agent-skills/asciicn/SKILL.md.

Skeleton

Loading placeholders for text, blocks and avatars made of shade glyphs, with a band of denser glyphs that sweeps across the page.

Controls
Motion
Glyphs
Colour
Cell12px

Installation

pnpm dlx shadcn@latest add https://asciicn.dev/r/skeleton.json

Usage

import { Skeleton } from "@/components/asciicn/skeleton";
 
export function PostLoading() {
  return (
    <div aria-busy="true" className="flex flex-col gap-3">
      <span className="sr-only">Loading post</span>
      <Skeleton rows={6} />
      <Skeleton shape="text" lines={3} />
    </div>
  );
}

A skeleton is rows of ░ the width of its container. Set the width with a class such as w-32; the height is rows cells, so it lines up with the glyph grid. shape="text" draws lines rows with a gap between them and a shorter last line, and shape="circle" draws a disc size rows across for avatars.

While it waits, a band of ▒▓▒ sweeps from left to right. The band's position comes from the viewport and a shared clock, so the sweep passes over every skeleton on the page as one light rather than each one starting on its own. motion="pulse" steps every glyph between ░ and ▒ instead. Swap the glyphs with chars, from resting to peak: "·•●" makes a dot skeleton, "⠂⠕⠿" a Braille one.

Examples

Cards and a panel

Each card keeps its real label while its value loads. The wide panel below uses chars="·•●", so it sweeps in dots instead of shades.

Table

Rows of a member table: a two-row disc for the avatar and single-row lines of different widths. One band crosses every cell of the table in step.

Props

PropTypeDefault
shape

A filled rectangle, lines of text, or a disc.

Type: "block" | "text" | "circle"Default "block"
rows

block: height in rows of cells.

Type: numberDefault 3
lines

text: number of lines. The last one is shorter.

Type: numberDefault 3
size

circle: diameter in rows of cells.

Type: numberDefault 3
motion

A dense band sweeping across, every glyph pulsing, or still.

Type: "sweep" | "pulse" | "none"Default "sweep"
chars

Glyphs from resting to the peak of the sweep.

Type: stringDefault "░▒▓"
color

Glyph colour, a palette name or any CSS colour.

Type: AsciiColorDefault "grey"
cell

Glyph cell height in CSS pixels.

Type: numberDefault --ascii-cell

Notes

  • Skeletons are aria-hidden. Mark the region that is loading with aria-busy="true" and give it a short status in text, such as a visually hidden "Loading post".
  • The first render, on the server too, is plain rows of the resting glyph, so there is no flash and no layout shift when the sweep starts.
  • The sweep redraws at 30fps, writing text straight into each line, and pauses offscreen and in hidden tabs. With reduced motion it holds the resting glyph.