Avatar
User portrait with an image, initials or icon, presence/company/verified indicators, a large profile photo, stacked groups, and an add-member button.
Installation
npx paubha@latest add avatarUsage
import { Avatar, AvatarAddButton, AvatarGroup, AvatarProfilePhoto } from "@/components/ui/avatar";
<Avatar src="/maya.jpg" alt="Maya Chen" />
<Avatar initials="MC" alt="Maya Chen" indicator="online" />
<AvatarProfilePhoto src="/maya.jpg" alt="Maya Chen" verified />
<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.
Type
type picks image, initials (bg-brand-subtle / fg-brand), or icon (Lucide User). When omitted it's inferred from what you pass.
Image and fallback
A missing or failing src falls back to initials; if neither initials nor alt can produce letters, the avatar shows the user icon.

Indicator
online (bg-success-solid) and offline (fg-disabled) render a presence dot with a bg-primary cutout; company and verified render a Building2 / BadgeCheck badge in fg-brand. The indicator is also written into the accessible name — keep a visible text label too when presence or verification affects a decision.
Profile photo
AvatarProfilePhoto is the large profile identity: sm 72px · md 96px · lg 160px, with a 4px bg-primary ring, shadow-md, and an optional verified badge.
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). size sm/md/lg/xl sets the avatar (32–64px) and the label type scale together.
Anastasia Upton
anastasia@example.com
Anastasia Upton
anastasia@example.com
Anastasia Upton
anastasia@example.com
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 the *Props interfaces in the registry source.
Avatar
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | — | Image URL. Falls back to initials, then the user icon, 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. |
| type | "image" | "initials" | "icon" | — | What to render. Defaults to `image` when `src` is set, else `initials` when letters can be derived, else `icon` (Lucide `User`). |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "md" | Diameter: 24 / 32 / 40 / 48 / 64 / 80px. |
| indicator | "none" | "online" | "offline" | "company" | "verified" | "none" | Bottom-right marker. Online = `bg-success-solid` dot, offline = `fg-disabled` dot, company/verified = Lucide `Building2`/`BadgeCheck` in `fg-brand`. Appended to the accessible name. |
AvatarProfilePhoto
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | — | Same as Avatar. |
| alt | string | — | Same as Avatar. |
| initials | string | — | Same as Avatar. |
| type | "image" | "initials" | "icon" | — | Same as Avatar. |
| size | "sm" | "md" | "lg" | "md" | Diameter: 72 / 96 / 160px, with a 4px `bg-primary` ring and `shadow-md`. |
| verified | boolean | false | Shows a `BadgeCheck` badge and appends ", verified" to the accessible name. |
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, `fg-primary`; type scales with `size`. |
| secondaryText | ReactNode | — | Optional supporting line (email, role), `fg-secondary`. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Avatar 32 / 40 / 48 / 64px; name 13 / 14 / 16 / 18px. |
Accessibility
Accessibility
Role. Each avatar is
role="img"with anaria-labelfromalt(orinitials). The indicator is appended to that name, e.g.Maya Chen, onlineorMaya Chen, verified, not a nested labelled node. Indicator glyphs arearia-hidden. 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.