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.

Avatar

An avatar drawn in glyphs: initials set over a lit disc of Braille dots, or a photo sampled into a glyph portrait, with a status glyph and overlapping groups.

Controls
Source
Name
Charset
Tint from name
Tint
Status
Shape

Installation

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

Usage

import { Avatar, AvatarGroup } from "@/components/asciicn/avatar";
 
export function Owner() {
  return <Avatar name="Ada Lovelace" status="online" />;
}
 
export function Photo() {
  return <Avatar name="Buzz Aldrin" src="/team/buzz.jpg" size="lg" />;
}
 
export function Viewers({ names }: { names: string[] }) {
  return (
    <AvatarGroup max={4} aria-label={`${names.length} viewers`}>
      {names.map((name) => (
        <Avatar key={name} name={name} />
      ))}
    </AvatarGroup>
  );
}

Without src, the avatar takes up to two initials from name ("Ada Lovelace" is AL, "deploy-bot" DB, "grace@navy.mil" G) and sets them in quadrant blocks (▘▝▖▗▀▄▌▐█), a pixel face whose solid 2×2 sub-cells stay legible even at 32px. They sit over a disc drawn in charset, Braille by default, whose mid tones are spread by ordered dithering. The disc is lit from the upper left, so it reads as a sphere, and it is tinted with a palette colour picked from name, so the same person always gets the same colour. A ring of blank samples around the letters keeps them clear of the disc.

With src, the photo is cover-fitted, area-averaged into the glyph grid, stretched to its full tonal range and drawn in any charset. In a light theme the tones flip, so dark parts of the photo get the dense glyphs. colorMode="truecolor" keeps the photo's colour per glyph.

The grid is always twice as many columns as rows, which makes it square. sm is 4 rows at 32px, md 6 rows at 48px, lg 8 rows at 72px and xl 12 rows at 112px. Pass a number for any size in pixels.

Examples

Photo portraits

The same photo at 160px in Braille, Dense 70, ANSI blocks, and Dense 70 in truecolor.

Group with a count

AvatarGroup overlaps each avatar by a quarter of its width, with a ring in outline between them. Past max, the rest collapse into a grey +n disc.

Members with presence

status sets a glyph in the corner. Each status has its own shape as well as its own colour: ● online, ◐ away, ■ busy, ○ offline. The bot uses shape="square" and a grey tint.

Props

Avatar

PropTypeDefault
name*

Who it is. Gives the initials, the default tint and the accessible name.

Type: stringDefault –
label

Accessible name, when it should differ from name.

Type: stringDefault name
src

A photo to draw as a glyph portrait instead of initials.

Type: stringDefault –
size

32, 48, 72 or 112px, or any size in pixels.

Type: "sm" | "md" | "lg" | "xl" | numberDefault "md"
charset

Glyphs to draw with.

Type: CharsetNameDefault "braille"
chars

A custom ramp from empty to dense. Wins over charset.

Type: stringDefault –
colorMode

With src: truecolor keeps the photo's colour per glyph.

Type: "mono" | "truecolor"Default "mono"
color

Tint of the disc or photo, a palette name or any CSS colour.

Type: AsciiColorDefault Picked from name
shape

A disc, or a square that fills the whole grid.

Type: "circle" | "square"Default "circle"
status

A status glyph in the corner.

Type: "online" | "away" | "busy" | "offline"Default –

AvatarGroup

PropTypeDefault
children*

The avatars, in order.

Type: ReactNodeDefault –
max

Show at most this many, then a +n count.

Type: numberDefault All
size

Size of every avatar in the group.

Type: "sm" | "md" | "lg" | "xl" | numberDefault "md"
outline

Colour of the ring between overlapping avatars.

Type: stringDefault "var(--ascii-paper)"

Notes

  • Each avatar is role="img" named by label or name, plus its status ("Ada Lovelace, online"). The glyphs are hidden from screen readers. Give the group an aria-label such as "9 viewers"; the count reads "and 5 more".
  • The disc is computed without a canvas, so it renders on the server with the initials as plain text over it. After mount, the initials are redrawn in glyphs; the box keeps its size, so nothing shifts.
  • Photos load with crossOrigin="anonymous", so images from another origin need CORS headers to be sampled. Until a photo loads, the avatar shows the initials disc.
  • Every avatar is a few hundred glyphs of DOM text. The grid is sampled once per change of name, photo, charset or theme, never per frame.