Experience System
Components

Avatar

An image with a fallback for people or entities—optional badge, stacked groups, and overflow count.

CNER
CNERLR

Installation

The component is exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.

Composition

Use the following composition to build a single Avatar:

Avatar
├── AvatarImage (optional; omit when using fallback only)
├── AvatarFallback
└── AvatarBadge (optional)

Stacked avatars share a row container:

AvatarGroup
├── Avatar (repeat)
└── AvatarGroupCount (optional)

Avatar wraps Radix UI Avatar Root, Image, and Fallback. AvatarBadge, AvatarGroup, and AvatarGroupCount are Experience System layout helpers (not Radix primitives).

Usage

import {
  Avatar,
  AvatarBadge,
  AvatarFallback,
  AvatarGroup,
  AvatarGroupCount,
  AvatarImage,
} from '@by/experience-system';

Avatar and its parts are client components ('use client' in the package). Use them inside a Client Component or a dynamic import when using the Next.js App Router. Wrap your tree in ThemeProvider where other Experience System components require it.

<Avatar>
  <AvatarImage src="/photo.png" alt="Ada Lovelace" />
  <AvatarFallback>AL</AvatarFallback>
</Avatar>

When to use

  • Identifying a person or account in headers, lists, comments, or pickers.
  • Showing a team or shared resource with AvatarGroup and an overflow AvatarGroupCount.
  • Indicating presence or status with AvatarBadge (dot, icon, or custom content).

When not to use

  • Placeholder loading skeletons—use Skeleton patterns instead of an empty Avatar.
  • Icons or brands with no person-like image and no fallback semantics—prefer Button (icon-only) or media components suited to the shape.

More usage references: Avatar (Confluence).

Examples

The live preview at the top of this page uses avatar-usage: a circular avatar, a square-cornered avatar, and a group where the last image fails so the fallback shows.

With badge

A small status indicator anchored on the avatar edge.

CN

Badge with icon

Use AvatarBadge with an icon (for example add or status). Icon content slightly enlarges the badge per default styles. Use only simple icons so the image remains clearly understandable at small sizes.

PP

Group

Overlap multiple Avatar roots with shared ring spacing; optional grayscale or other utilities on the group.

CNLRER

Group with count

Show visible members plus an overflow pill (AvatarGroupCount) for additional participants.

CNLRER
+3

API Reference

Subsection titles name @by/experience-system exports. Avatar, AvatarImage, and AvatarFallback mirror Radix UI Avatar. The tables list Radix-documented props; each part also accepts standard attributes for its underlying element (span for Avatar / AvatarFallback, img for AvatarImage) unless asChild merges props onto a child.

Design-system additions: data-slot on each part, default className merging for size, shape, colors, and group overlap—override with your own className as needed.

Avatar

Radix Avatar.Root (renders a span).

PropTypeDefault
asChildbooleanfalse

Also accepts React.ComponentPropsWithoutRef<'span'> from the Radix primitive (for example className, children, event handlers). This experience system sets data-slot="avatar" and default circular sizing.

AvatarImage

Radix Avatar.Image (renders an img when loaded).

PropTypeDefault
asChildbooleanfalse
onLoadingStatusChange(status: 'idle' | 'loading' | 'loaded' | 'error') => void

Also accepts standard img attributes (src, alt, crossOrigin, referrerPolicy, …). This experience system sets data-slot="avatar-image".

AvatarFallback

Radix Avatar.Fallback (renders a span when the image is not shown).

PropTypeDefault
asChildbooleanfalse
delayMsnumber

Also accepts standard span attributes. This experience system sets data-slot="avatar-fallback" and default neutral surface styles for initials.

AvatarBadge

Design-system span overlay for status or icons—not part of Radix Avatar.

PropTypeDefault
Accepts React.ComponentPropsWithoutRef<'span'>

Renders with data-slot="avatar-badge" and default accent positioning; pass className or aria-label for custom status semantics.

AvatarGroup

Design-system div flex row with negative horizontal spacing and per-avatar rings.

PropTypeDefault
Accepts React.ComponentPropsWithoutRef<'div'>

Uses data-slot="avatar-group"; supports rtl:space-x-reverse for RTL stacks.

AvatarGroupCount

Design-system div styled like an extra avatar cell for overflow text (for example +3).

PropTypeDefault
Accepts React.ComponentPropsWithoutRef<'div'>

Uses data-slot="avatar-group-count"; pair with aria-label when the text alone is not descriptive.

Accessibility

Provide meaningful alt text on AvatarImage when the photo conveys identity; use an empty alt="" only when the image is purely decorative and the same information is available elsewhere. AvatarFallback should remain readable (sufficient contrast) and concise (initials or a short label). For AvatarBadge, add aria-label (or visible text) when the badge communicates state. If the entire avatar opens a menu or navigates, compose with a real button or link (for example Avatar asChild around Button) so keyboard and screen-reader users get a proper control—see Radix Avatar and your product keyboard guidelines.

Source in the repo: packages/experience-system/src/components/Avatar/Avatar.tsx. Agent-oriented contracts: packages/experience-system/src/components/Avatar/Avatar.instructions.md.