AvatarGroup
Displays a stack of avatars with overflow handling.
Installation
npx vayu-ui-cli@latest add avatar-groupUsage
Avatar Group Examples
Basic Stack


Grid Layout (All Visible)



Sizes








Interactive (Click avatars to select)



With Overflow


Status Indicators


Anatomy
<AvatarGroup>
{/* Root container — role="group" */}
<AvatarItem>
{/* Per-user avatar wrapper with Avatar inside */}
<Avatar>
<Avatar.Image />
<Avatar.Status />
</Avatar>
</AvatarItem>
<AvatarItem>...</AvatarItem>
<OverflowButton>{/* "+N" indicator shown when users exceed maxDisplay */}</OverflowButton>
</AvatarGroup>| Part | Description |
|---|---|
| Root | Flex container with role="group" and keyboard handling |
| AvatarItem | Per-user wrapper — renders Avatar with positioning |
| OverflowButton | Button showing remaining count when overflow occurs |
Accessibility
Keyboard Support
| Key | Behavior |
|---|---|
ArrowRight | Move focus to the next interactive avatar |
ArrowLeft | Move focus to the previous interactive avatar |
Tab | Move focus into and out of the avatar group |
Enter | Activate the focused clickable avatar |
Space | Activate the focused clickable avatar |
ARIA Attributes
| Element | Attribute | Value |
|---|---|---|
| Root | role | group |
| Root | aria-label | Avatar group with {count} members |
| Avatar (static) | aria-label (from Avatar) | {username}'s avatar |
| Avatar (clickable) | role | button |
| Avatar (clickable) | tabIndex | 0 |
| OverflowButton | role | button |
| OverflowButton | aria-label | Show {count} more users |
Focus Behavior
- Focus is managed via roving tabindex on interactive avatars (
role="button") focus-visiblering usesring-focusdesign token with offset- All hover animations respect
prefers-reduced-motionviamotion-safe:prefix - Minimum touch target of 24x24px (WCAG 2.5.5)
Screen reader behavior
A screen reader announces the group as "Avatar group with N members, list" followed by each avatar individually. Each avatar is announced using the username property (e.g., "John Doe's avatar, image"). Avatars without an image source fall back to the initials text. When the overflow button is present, it is announced as "Show N more users, button".
Component Folder Structure
AvatarGroup/
├── AvatarGroup.tsx # Composition — data processing + layout
├── AvatarItem.tsx # Individual avatar wrapper with positioning
├── AvtarGroupOverflowButton.tsx # "+N more" overflow indicator
├── hooks.ts # Spacing calculation and keyboard navigation
├── types.ts # Type definitions
├── index.ts # Public API exports
└── README.mdProps
AvatarGroup
| Prop | Type | Default | Description |
|---|---|---|---|
users | UserData[] | [] | Array of user objects to display |
size | "small" | "medium" | "large" | "xlarge" | "medium" | Size of each avatar |
maxDisplay | number | 5 | Maximum visible avatars before overflow |
layout | "stack" | "grid" | "stack" | Layout mode for the group |
spacing | "tight" | "normal" | "loose" | number | "normal" | Overlap offset for stack layout |
renderOverflow | (count: number) => React.ReactNode | — | Custom render for the overflow indicator |
onAvatarClick | (user: UserData, index: number) => void | — | Click handler for individual avatars |
onOverflowClick | (hiddenUsers: UserData[]) => void | — | Click handler for the overflow button |
UserData
| Prop | Type | Description |
|---|---|---|
id | string | number | null | Unique identifier for the user |
src | string | Image URL for the avatar |
username | string | Display name, used as alt text |
alt | string | Alt text for the avatar image |
fallback | string | Initials shown when no image |
status | "online" | "offline" | "away" | "busy" | Status indicator on the avatar |
Size Reference
| Size | Dimensions |
|---|---|
small | 32x32px |
medium | 48x48px |
large | 64x64px |
xlarge | 96x96px |
Spacing Reference
| Spacing | Stack Offset |
|---|---|
tight | -12px |
normal | -8px |
loose | -4px |