Avatar

A person’s photo, initials or icon, with an optional border and presence dot.

Installation

bash
npx @smicolon/cli init
npx @smicolon/cli add avatar status-indicator

The avatar uses status-indicator for its dot, so add both.

Preview

Layla HaddadLayla HaddadLayla HaddadOnline

Variants

variant picks the content. image, the default, shows the photo, and while it loads or if it fails falls back to initials from name, then to the user icon when there is no name. initials and icon show theirs even when a photo is passed. radius picks a rounded square or a circle, and border adds a ring inside the edge.

If the photo is missing or fails to load, the avatar shows the initials, or the icon if there's no name.

Layla HaddadLayla HaddadLayla HaddadstandardLayla HaddadLayla HaddadLayla Haddadstandard + borderLayla HaddadLayla HaddadLayla HaddadroundedLayla HaddadLayla HaddadLayla Haddadrounded + border

Sizes

32 for headers, cards and comments; 24 for dense tables and lists; 12 for inline mentions, where initials shrink to one letter at the 10px XXS size.

Layla HaddadLayla Haddad
Layla HaddadLayla Haddad
Layla HaddadLayla Haddad

Status

status adds a Status Indicator at the end corner — bottom-right, or bottom-left in a right-to-left page. There is no dot unless you set one: it claims the person’s presence, so show it only when you know it.

Layla HaddadOnlineLayla HaddadAwayLayla HaddadBusyLayla HaddadOfflineLayla HaddadOnline

Accessibility

  • name names the avatar in every variant: it is the photo’s alt, and hidden text behind the initials or icon, whose visible letters are not read out.
  • Pass name="" when a label beside the avatar already names the person, so it isn’t announced twice.
  • The dot is read after the name — "Layla Haddad", then "Online", or "متصل" when the nearest lang is Arabic. Pass statusLabel to say more.
  • Direction is inherited from dir, never a prop, so the dot always sits on the right corner for the page.

Props

PropTypeDefaultDescription
variant"image" | "initials" | "icon""image"What it shows: photo, initials or icon.
size"32" | "24" | "12""32"Avatar size in pixels.
radius"standard" | "rounded""standard"Rounded square or circle.
borderbooleanfalseAdds a ring inside the edge.
srcstring—Photo URL.
namestring—Person’s name: the alt text and initials.
status"online" | "away" | "busy" | "offline"—Adds a presence dot.
statusLabelstring—Dot’s accessible name, in the page language by default.
classNamestring—Extra classes for the component.

Usage

tsx
import { Avatar } from "@/components/ui/avatar"

// Photo, falling back to initials, then the user icon
<Avatar src={user.photo} name={user.name} />

// Initials or the icon, whatever else is passed
<Avatar variant="initials" name={user.name} />
<Avatar variant="icon" name={user.name} />

// Long lists: defer photos below the fold, and give dense screens a sharper source
<Avatar src={user.photo} srcSet={`${user.photo} 1x, ${user.photo2x} 2x`} loading="lazy" name={user.name} />

// Circle with a border and a presence dot
<Avatar src={user.photo} name={user.name} radius="rounded" border status="online" />

// Inline, beside a name that already says who it is
<Avatar size="12" src={user.photo} name="" /> {user.name}