Components

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.

Updated Jul 17, 2026 by Leonardo Posada

Anatomy

YJ
  1. 1
    Avatar (root)

    Radix Root. Circular container, size-controlled via the size prop (xs / sm / md / lg / xl). Shares its size with children through context.

  2. 2
    AvatarImage

    Optional. The user's photo, aspect-square filling the circle. If it fails to load or is absent, Radix renders the AvatarFallback instead.

  3. 3
    AvatarFallback

    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.

  4. 4
    AvatarIcon

    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.

Jxs · 20
Jsm · 24
Jmd · 32
Jlg · 40
Jxl · 48
<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).

Image

The ideal case - real photo passed via AvatarImage src. Always include alt with the user's name.

Y
<Avatar>
  <AvatarImage src="/julian.png" alt="Julián Núñez" />
  <AvatarFallback>J</AvatarFallback>
</Avatar>
Fallback

One uppercase letter on bg-muted. Pass a single char OR a full name - the component slices to the first character for you.

JJ
{/* Explicit single letter */}
<Avatar>
  <AvatarFallback>J</AvatarFallback>
</Avatar>

{/* String children get sliced to first char automatically */}
<Avatar>
  <AvatarFallback>Julián Núñez</AvatarFallback>
</Avatar>
Icon

Neutral placeholder (white surface + border + Phosphor User light) when there is no photo AND no meaningful initial.

<Avatar>
  <AvatarIcon />
</Avatar>

One letter only

Yuno avatars display exactly one uppercase letter as the fallback. If you pass a full name to AvatarFallback (e.g. 'Julián Núñez'), the component slices to the first character for you. Never override this rule with two-letter initials.

Recipes

Ready-to-copy compositions covering the most common Yuno usages of this atom.

User profile row

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.

J
Julián Núñezjulian@yuno.io
<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>
Account menu trigger

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>
Table row user

Tiny avatar (size xs, 20px) + label inline. For dense tables where every row shows the acting user (audit logs, transactions, activity).

MMaría López
<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>
Team avatar stack

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.

ABC
<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.

Full compound. Import only what you use.
import {
  Avatar,
  AvatarImage,
  AvatarFallback,
  AvatarIcon,
} from "@/components/ui/avatar";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
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.classNamestringMerged with base classes via cn(). Use to add ring-2 ring-background for stacked avatars, or override the neutral defaults.
Avatar.asChildbooleanfalseInherited from Radix Root. Rare — Avatar is not focusable by default.
AvatarImage.srcstringPhoto URL. If it fails or is missing, Radix renders the AvatarFallback instead.
AvatarImage.altstringRequired for accessibility. Use the person's name so screen readers announce the identity.
AvatarImage.onLoadingStatusChange(status: "idle" | "loading" | "loaded" | "error") => voidFires when the image state changes. Useful if you want to log a fallback event.
AvatarImage.classNamestringMerged. Base is aspect-square size-full so the image fills the circular Root.
AvatarFallback.childrenReactNodeString 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.delayMsnumberWait this many ms before showing the fallback. Prevents flash while the image loads.
AvatarFallback.classNamestringMerged. Base is bg-muted text-foreground with text-xs at size xs and text-sm at every other size.
AvatarIcon.classNamestringMerged. 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

Do
  • 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
  • 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.