Skip to content
Component installs need the registry setup— the Base UI shadcn project, the @vegastack namespace and the Cloudflare Access service token.
VegaStack Design

Avatar

A circular user or entity image with an initials fallback, five sizes, and an overlapping AvatarGroup stack.

Status
stable
Since
0.1.0
Accessibility pattern
image with text fallback

Last updated

ALLT

Install

Add Avatar from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.

pnpm dlx shadcn@latest add @vegastack/avatar

Usage

import { Avatar, AvatarGroup } from "@/components/ui/avatar";

<Avatar
  src="https://cdn.example.com/u/ada.webp"
  alt="Ada Lovelace"
  fallback="AL"
/>;

Presentational only. Avatar takes a fully-resolved, public src. It does not fetch data or resolve storage keys — resolving an R2 (or any CDN) key to a public URL stays app-side, so resolve it before passing src. The image only paints once it has loaded; until then (or on error) the fallback shows, so there is never a broken-image icon.

Anatomy

Avatar is a compound component. Every exported part, with the data-slot it renders (generated from the canonical source):

Avatar — data-slot="avatar" | "avatar-fallback" | "avatar-image"
AvatarGroup — data-slot="avatar-group"

Examples

Anatomy

Avatar wraps Base UI Avatar.RootAvatar.ImageAvatar.Fallback behind a single flat prop API. AvatarGroup is a layout shell that overlaps its Avatar children.

<AvatarGroup>
  <Avatar src={url} alt="…" fallback="AL" /> {/* Root → Image → Fallback */}
  <Avatar fallback="+5" /> {/* overflow indicator (no src → fallback) */}
</AvatarGroup>

Sizes

xs, sm, default, lg, and xl — the diameter and the fallback text scale together.

ALALALALAL

Fallback

When src is absent or the image fails to load, the fallback shows — typically 1–2 uppercase initials, or an icon. Without a fallback, the bare bg-accent circle remains.

ALLT

Both the no-src path and the image-error path resolve to the same fallback, so a broken or unreachable src never leaves a broken-image icon — it falls back to the initials (or icon):

ALno src
ALbroken src
icon fallback

Fallback delay

fallbackDelay (ms) waits before swapping in the fallback, avoiding a flash of initials for fast-loading images — the bare bg-accent circle holds the space until either the image paints or the delay elapses. It is forwarded to Base UI Avatar.Fallback.

<Avatar src={url} alt="Ada Lovelace" fallback="AL" fallbackDelay={600} />

Group

AvatarGroup overlaps its children into a stack and gives each a ring-background so the overlap reads cleanly on any surface. Add a trailing Avatar with a +N fallback to indicate overflow. Control overlap density with spacing (tight · default · loose).

ALLTGH+5

The three spacing values side by side — tight tucks each avatar furthest under the previous, loose overlaps the least:

ALLTGH+5
tight
ALLTGH+5
default
ALLTGH+5
loose

Playground

Adjust the avatar size and the group's overlap spacing, then copy the generated JSX.

ALGH+3
<AvatarGroup>
  <Avatar fallback="AL" />
  <Avatar fallback="GH" />
  <Avatar fallback="+3" />
</AvatarGroup>

API Reference

Avatar

PropTypeDefaultDescription
altstringAccessible alt text describing who/what the avatar represents (usually the person's name). Pass alt="" only when the avatar image is purely decorative and an adjacent control/text already names the entity. Optional because no <img> is rendered when src is absent.
fallbackReact.ReactNodeFallback content shown while the image loads or when it fails / is absent — typically 1–2 uppercase initials. Falls back to rendering nothing (the bare bg-accent circle) when omitted.
fallbackDelaynumberHow long to wait (ms) before showing the fallback, to avoid a flash for fast-loading images. Forwarded to Base UI Avatar.Fallback.
size"lg" | "md" | "sm" | "xl" | "xs"'md'Diameter of the avatar — also scales the fallback text.
srcstringImage source. Pass a fully-resolved, public URL — this component is purely presentational and does NOT resolve storage keys. R2 (or any CDN) key → URL resolution stays app-side; resolve before passing src. No image source; only the fallback/root renders.

Data attributes and CSS variables on Avatar

AttributeValues
data-sizemirrors a prop or state value
data-slot"avatar" | "avatar-fallback" | "avatar-image"

AvatarGroup

PropTypeDefaultDescription
spacing"default" | "loose" | "tight"'default'Overlap density of the stack. - tight: avatars tuck furthest under one another. - default: balanced overlap (default). - loose: minimal overlap.

Data attributes and CSS variables on AvatarGroup

AttributeValues
data-slot"avatar-group"

Accessibility

  • When src is provided, alt is required. Pass the person's or entity's name for meaningful avatars; pass alt="" only when adjacent text or the wrapping control already names the entity.
  • When src is absent, no <img> is rendered; the fallback/root carries the visible identity.
  • The fallback (initials or icon) is the visible label when no image loads; keep it meaningful (initials of the same name) so the avatar stays identifiable without the picture.
  • Avatar is non-interactive by default. When an avatar links to a profile, wrap it in an interactive element (a Button/link) that owns the accessible name and focus ring — don't rely on the image alone.
KeyAction
TabMoves focus only when the avatar is wrapped in an interactive element (link/button).
ContractStates tested
Behaviourdefault, error, loading, selected
Accessibilitynative-or-base-ui-semantics, browser-accessibility-test
Visualdefault, loading, error

Do / Don't

Do
Pass a resolved public src plus an alt with the person's name, and a fallback with their initials so the avatar stays identifiable while loading or on error.
Don't
Pass a raw R2/storage key as src or skip the fallback — resolve keys app-side, and always provide initials so a failed image doesn't leave an empty circle.

On this page