Avatar
An image element with a fallback for representing the user.
Installation
npx vayu-ui-cli@latest add avatarUsage
Avatar Examples
Sizes
Small
Medium
Large
Extra Large
Variants
Image
Initials

Fallback
Status States
Online
Away
Busy
Offline
Interactive
Click or focus these avatars to see WCAG-compliant interactions.
Button
With Status
With Button Component
Avatars can be used inside buttons for profile actions.
<Avatar size="small" username="Small User">
<Avatar.Initials username="Small User" />
</Avatar>
<Avatar size="medium" username="Rugved Patel">
<Avatar.Initials username="Rugved Patel" />
</Avatar>
<Avatar size="large" username="John Doe">
<Avatar.Image
src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=800&auto=format&fit=crop&q=60"
alt=""
/>
</Avatar>
<Avatar size="large" username="Fallback User">
<Avatar.Image src="https://broken-image-link.com/image.jpg" alt="" />
<Avatar.Fallback />
</Avatar>
<Avatar size="large" username="Online" status="online">
<Avatar.Initials username="Online" />
<Avatar.Status status="online" />
</Avatar>
<Avatar
size="large"
username="Profile"
onClick={() => console.log("clicked")}
>
<Avatar.Initials username="Profile" />
</Avatar>
<Avatar size={40} username="Custom Size">
<Avatar.Initials username="Custom Size" />
</Avatar>Anatomy
<Avatar size="medium" username="John Doe">
<Avatar.Image src="https://example.com/avatar.jpg" alt="" />
<Avatar.Fallback />
<Avatar.Initials username="John Doe" />
<Avatar.Status status="online" />
</Avatar>| Element | Description |
|---|---|
| Avatar | Root container providing size, shape, and accessibility context |
| Avatar.Image | Displays a profile image with loading state and error fallback |
| Avatar.Fallback | Default image shown when primary image fails to load |
| Avatar.Initials | Auto-generated initials with deterministic background color |
| Avatar.Status | Status indicator dot (online, offline, away, busy) |
Accessibility
Keyboard Support
- Interactive avatars (with
onClick) receivetabIndex={0}and can be focused via Tab - Enter and Space activate the
onClickhandler - Static avatars are not focusable
ARIA Attributes
| Element | Role | ARIA Attributes |
|---|---|---|
| Avatar (static) | img | aria-label="{username}'s avatar" |
| Avatar (interactive) | button | aria-label="{username}'s avatar", tabIndex={0} |
| Avatar.Status | status | aria-label="{status}", aria-live="polite" |
| Loading spinner | status | aria-busy="true", aria-label="Loading avatar image" |
Focus Behavior
- Visible 2px focus ring with offset using
focus-visible:ring-2 focus-visible:ring-focus - Focus ring is styled consistently in both light and dark modes
- Focus only appears on keyboard navigation, not on click (
focus-visible)
Screen reader behavior
- Static avatars are announced as an image: "John Doe's avatar"
- Interactive avatars are announced as a button: "John Doe's avatar, button"
- When
statusis set on the root, it appends to the label: "John Doe's avatar (online)" - Status indicators are announced via
aria-live="polite"when the status changes - Loading state is announced as "Loading avatar image" via
aria-busy="true" - Initials and fallback images are hidden from screen readers (
aria-hidden="true") since the parent provides the label
Component Folder Structure
Avatar/
├── Avatar.tsx # Root component + compound pattern wiring
├── AvatarImage.tsx # Image with loading spinner and fallback support
├── AvatarInitials.tsx # Generated initials with background color
├── AvatarFallback.tsx # Default avatar image
├── AvatarStatus.tsx # Status indicator dot
├── hooks.ts # Initial generation and color hashing
├── types.ts # Types and WCAG-compliant color palette
├── index.ts # Public API barrel export
└── README.mdProps
Avatar (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
size | "small" | "medium" | "large" | "xlarge" | number | "medium" | Size of the avatar container |
username | string | "" | Used for aria-label and initials generation |
alt | string | - | Custom alt text for the avatar |
status | "online" | "offline" | "away" | "busy" | - | Appends status context to the aria-label |
onClick | () => void | - | Makes the avatar interactive (button role) |
tabIndex | number | 0 | Tab index when interactive |
className | string | - | Additional CSS classes |
children | ReactNode | - | Subcomponents (Image, Initials, Fallback, Status) |
Avatar.Image
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | Image source URL |
fallbackSrc | string | - | Secondary URL used if primary src fails |
alt | string | "" | Alt text for the image |
onError | (e: SyntheticEvent) => void | - | Callback when image fails to load |
onLoad | (e: SyntheticEvent) => void | - | Callback when image loads successfully |
className | string | - | Additional CSS classes |
Avatar.Initials
| Prop | Type | Default | Description |
|---|---|---|---|
username | string | - | Name to generate initials and background color |
className | string | - | Additional CSS classes |
Avatar.Fallback
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | Placeholder URL | Default image when primary image fails |
alt | string | "Default avatar" | Alt text for the fallback image |
className | string | - | Additional CSS classes |
Avatar.Status
| Prop | Type | Default | Description |
|---|---|---|---|
status | "online" | "offline" | "away" | "busy" | - | Status to display visually |
label | string | - | Accessible label (overrides default) |
className | string | - | Additional CSS classes |