Avatar
Circular container for a user identity. Shows a photo when available; otherwise falls back to a single letter on a muted background. Built on Radix Avatar.
Anatomy
- 1Avatar (root)
Radix Root. Circular container, size-controlled via the size prop (xs / sm / md / lg / xl). Shares its size with children through context.
- 2AvatarImage
Optional. The user's photo, aspect-square filling the circle. If it fails to load or is absent, Radix renders the AvatarFallback instead.
- 3AvatarFallback
Single uppercase letter on bg-muted. Yuno rule: string children are auto-sliced to the first character. Font size drops to text-xs at size xs, text-sm otherwise.
- 4AvatarIcon
Generic placeholder type: white surface + neutral border + Phosphor User (light). Use when there is no photo AND no meaningful initial.
Sizes
Five fixed sizes matching the Yuno Figma scale: xs=20 / sm=24 / md=32 / lg=40 / xl=48. Default is md. Never inline a custom size - pick the closest token so avatars align across the Dashboard.
<Avatar size="xs"><AvatarFallback>J</AvatarFallback></Avatar> {/* 20px */}
<Avatar size="sm"><AvatarFallback>J</AvatarFallback></Avatar> {/* 24px */}
<Avatar size="md"><AvatarFallback>J</AvatarFallback></Avatar> {/* 32px, default */}
<Avatar size="lg"><AvatarFallback>J</AvatarFallback></Avatar> {/* 40px */}
<Avatar size="xl"><AvatarFallback>J</AvatarFallback></Avatar> {/* 48px */}Types
Three ways to fill the circle. Image is the ideal case. Fallback is the muted-letter default. Icon is the neutral placeholder when you have neither photo nor initial (e.g. anonymous, team seat, unassigned).
The ideal case - real photo passed via AvatarImage src. Always include alt with the user's name.
<Avatar>
<AvatarImage src="/julian.png" alt="Julián Núñez" />
<AvatarFallback>J</AvatarFallback>
</Avatar>One uppercase letter on bg-muted. Pass a single char OR a full name - the component slices to the first character for you.
{/* Explicit single letter */}
<Avatar>
<AvatarFallback>J</AvatarFallback>
</Avatar>
{/* String children get sliced to first char automatically */}
<Avatar>
<AvatarFallback>Julián Núñez</AvatarFallback>
</Avatar>Neutral placeholder (white surface + border + Phosphor User light) when there is no photo AND no meaningful initial.
<Avatar>
<AvatarIcon />
</Avatar>One letter only
Recipes
Ready-to-copy compositions covering the most common Yuno usages of this atom.
Avatar + name + email. The canonical pattern for the account header, user cards, and settings pages. Use size lg so the two lines of text align next to the circle.
<div className="flex items-center gap-3">
<Avatar size="lg">
<AvatarImage src="/julian.png" alt="Julián Núñez" />
<AvatarFallback>J</AvatarFallback>
</Avatar>
<div className="grid">
<span className="text-sm font-medium text-foreground">Julián Núñez</span>
<span className="text-xs text-muted-foreground">julian@yuno.io</span>
</div>
</div>Compact button (size md avatar + CaretDown) that opens the AccountMenu dropdown. Lives at the far right of the TopBar. Requires aria-label because the visible content is just the letter.
<button
type="button"
aria-label="Open account menu"
className="inline-flex items-center gap-2 rounded-md p-1 hover:bg-accent"
>
<Avatar size="md">
<AvatarFallback>L</AvatarFallback>
</Avatar>
<CaretDown weight="light" className="size-4 text-muted-foreground" />
</button>Tiny avatar (size xs, 20px) + label inline. For dense tables where every row shows the acting user (audit logs, transactions, activity).
<div className="flex items-center gap-2">
<Avatar size="xs">
<AvatarFallback>M</AvatarFallback>
</Avatar>
<span className="text-sm text-foreground">María López</span>
</div>Overlapping row of avatars with -space-x-2 and ring-2 ring-background so each circle stays crisp against its neighbor. Reserve for compact team / member summaries.
<div className="flex -space-x-2">
<Avatar size="sm" className="ring-2 ring-background">
<AvatarFallback>A</AvatarFallback>
</Avatar>
<Avatar size="sm" className="ring-2 ring-background">
<AvatarFallback>B</AvatarFallback>
</Avatar>
<Avatar size="sm" className="ring-2 ring-background">
<AvatarFallback>C</AvatarFallback>
</Avatar>
<Avatar size="sm" className="ring-2 ring-background">
<AvatarIcon />
</Avatar>
</div>Import
Copy this import line at the top of the file where you compose this atom.
import {
Avatar,
AvatarImage,
AvatarFallback,
AvatarIcon,
} from "@/components/ui/avatar";Props
Everything else from the underlying HTML or Radix primitive is forwarded via ...props.
| Prop | Type | Default | Description |
|---|---|---|---|
| Avatar.size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Yuno scale: xs=20px, sm=24px, md=32px, lg=40px, xl=48px. Shared via context so AvatarFallback text and AvatarIcon glyph scale together. |
| Avatar.className | string | — | Merged with base classes via cn(). Use to add ring-2 ring-background for stacked avatars, or override the neutral defaults. |
| Avatar.asChild | boolean | false | Inherited from Radix Root. Rare — Avatar is not focusable by default. |
| AvatarImage.src | string | — | Photo URL. If it fails or is missing, Radix renders the AvatarFallback instead. |
| AvatarImage.alt | string | — | Required for accessibility. Use the person's name so screen readers announce the identity. |
| AvatarImage.onLoadingStatusChange | (status: "idle" | "loading" | "loaded" | "error") => void | — | Fires when the image state changes. Useful if you want to log a fallback event. |
| AvatarImage.className | string | — | Merged. Base is aspect-square size-full so the image fills the circular Root. |
| AvatarFallback.children | ReactNode | — | String children get sliced to the first uppercase character (Yuno rule: one letter only). Non-string children render as-is (rare — reserve for scope icons). |
| AvatarFallback.delayMs | number | — | Wait this many ms before showing the fallback. Prevents flash while the image loads. |
| AvatarFallback.className | string | — | Merged. Base is bg-muted text-foreground with text-xs at size xs and text-sm at every other size. |
| AvatarIcon.className | string | — | Merged. Base is white surface (bg-background) + border-border + Phosphor User (light). The glyph size auto-scales with the Avatar size prop. |
When to use
- In the AccountMenu trigger and user card.
- In tables or lists that display a user or account per row.
- Anywhere identity needs to appear compactly.
When not to use
- For decorative graphics — use an icon or illustration.
- For status indicators — use Badge instead.
- As the primary trigger for a menu with no identity context — a plain IconButton is enough.
Usage
- Single letter only inside the circle. Never pair of initials, never two letters.
- Uppercase the fallback letter.
- Provide alt text on AvatarImage so screen readers announce the user identity.
- Match the ring color to the surface it sits on so the circle stays crisp.
- Don't put text longer than one character inside the fallback.
- Don't nest icons in the fallback for a user avatar — reserve that pattern for scope icons (Buildings, Storefront).
- Don't color-code the fallback per user — the DS keeps them neutral (bg-muted).
Related
Cross-links to atoms and patterns you may reach for next.
- Account menuThe organism that consumes Avatar as its trigger and its user card.
- BadgeFor status indicators (online, verified) - never color-code the fallback.
- SidebarUses avatars inside the account menu block at the bottom.
- Hover cardWrap an avatar to reveal a richer user preview on hover.