Avatar
User portrait with an image, initials fallback, optional status, stacked groups, and an add-member button.
Installation
npx asteria-ui add avatarUsage
import { Avatar, AvatarAddButton, AvatarGroup } from "@/components/ui/avatar";
<Avatar src="/maya.jpg" alt="Maya Chen" />
<Avatar initials="MC" alt="Maya Chen" status="online" />
<AvatarGroup max={3}>
<Avatar src="/maya.jpg" alt="Maya Chen" />
<Avatar src="/rio.jpg" alt="Rio Patel" />
<Avatar initials="KO" alt="Ken Okada" />
<Avatar initials="AS" alt="Ana Silva" />
</AvatarGroup>Examples
Sizes
xs 24px · sm 32px · md 40px · lg 48px · xl 64px · 2xl 80px.
Image and fallback
A missing or failing src falls back to initials on bg-brand-subtle with fg-brand text. If neither src nor initials/alt can produce letters, the avatar shows ?.

Status
Optional presence dot. Online uses success-500; offline uses gray-300. The cutout ring is bg-primary so it punches through the portrait.
Avatar group
Stacked, overlapping avatars with a +N overflow chip (bg-secondary / fg-secondary). Each face gets a border-default ring and a bg-primary stack cutout.
Label group
Pairs an avatar with a name and optional secondary text (email, role) — for lists, comment authors, and member rows.
Anastasia Upton
anastasia@example.com
Add-member button
A dashed-border circular button for adding another person to a group. Sizes match Avatar's own md/lg/xl. The hover state (border-brand + the signature glow-focus shadow) is also applied on focus-visible, since Figma's mockup only shows hover but every interactive component needs a visible keyboard focus indicator.
Composed after an AvatarGroup:
API reference
Prop names and types are taken from AvatarProps / AvatarGroupProps in the registry source.
Avatar
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | — | Image URL. Falls back to initials if missing or it fails to load. |
| alt | string | — | Accessible name. Also used to derive initials when `initials` is omitted. |
| initials | string | — | Fallback letters on `bg-brand-subtle` / `fg-brand`. Max two characters. |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "md" | Diameter: 24 / 32 / 40 / 48 / 64 / 80px. |
| status | "online" | "offline" | — | Optional presence dot. Online uses success-500; offline uses gray-300. |
AvatarGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| max | number | 4 | How many avatars to show before a +N overflow chip. |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "md" | Applied to every child and the overflow chip. |
| children | ReactNode | — | One or more `<Avatar />` elements. |
AvatarAddButton
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "md" | "lg" | "xl" | "md" | Diameter: 40 / 48 / 64px, matching Avatar's own md/lg/xl. |
| aria-label | string | "Add" | Accessible name — the "+" glyph itself is decorative. |
AvatarLabelGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| avatar | ReactNode | — | An `<Avatar />` element — its `size` is overridden to match. |
| name | ReactNode | — | Primary line — `text-ui-sm` / `fg-primary`. |
| secondaryText | ReactNode | — | Optional supporting line (email, role) — `text-ui-xs` / `fg-secondary`. |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "md" | Passed through to the avatar. |
Accessibility
Accessibility
Role. Each avatar is
role="img"with anaria-labelfromalt(orinitials). Status is appended to that name —Maya Chen, online— not a nested labelled node. The inner<img>usesalt=""so it isn't announced twice.Keyboard. Avatar is presentational. It is not focusable and has no activation keys. Wrap it in a link or button if it should be interactive.
ARIA.
AvatarGroupusesrole="group". Overflow is its ownrole="img"labelledN more.AvatarAddButton is a native
<button>— Enter/Space activates, and it accepts an accessible name viaaria-label(defaults to"Add"). Its focus ring uses the sameshadow-glow-focustreatment as its hover state.