Avatar
An image with a fallback for people or entities—optional badge, stacked groups, and overflow count.
Installation
The component is exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn 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
AvatarGroupand an overflowAvatarGroupCount. - Indicating presence or status with
AvatarBadge(dot, icon, or custom content).
When not to use
- Placeholder loading skeletons—use
Skeletonpatterns instead of an emptyAvatar. - 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.
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.
Group
Overlap multiple Avatar roots with shared ring spacing; optional grayscale or other utilities on the group.
Group with count
Show visible members plus an overflow pill (AvatarGroupCount) for additional participants.
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).
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
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).
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
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).
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
delayMs | number | — |
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.
| Prop | Type | Default |
|---|---|---|
| — | 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.
| Prop | Type | Default |
|---|---|---|
| — | 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).
| Prop | Type | Default |
|---|---|---|
| — | 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.