Import
import { Avatar, AvatarFallback, AvatarImage } from "@timelycare/helix-ui"
Props
interface AvatarProps {
className?: string
children: React.ReactNode
}
interface AvatarImageProps {
src: string
alt: string
className?: string
onLoadingStatusChange?: (status: "loading" | "loaded" | "error") => void
}
interface AvatarFallbackProps {
className?: string
children: React.ReactNode // Typically 1-2 character initials
delayMs?: number // Delay before showing fallback
}
Variants
| Variant | Use For | Implementation |
|---|---|---|
| Image | User has profile picture | <AvatarImage src="..." /> |
| Fallback | No image or image fails | <AvatarFallback>CN</AvatarFallback> |
Shapes
| Shape | Default | Use For | Circle Radius | Rounded Radius (size-dependent) |
|---|---|---|---|---|
| Rounded | Yes | All standard contexts: workspace, team, nav, app | — | See table below |
| Circle | No | Social media profiles, legacy circular UIs only — opt-in, not the default | rounded-full | — |
Rounded Shape Radius by Size
| Size | Rounded Radius | Tailwind |
|---|---|---|
| 12 (48px) | 16px | rounded-2xl |
| 10 (40px) | 14px | rounded-xl |
| 8 (32px) | 10px | rounded-lg |
| 6 (24px) | 8px | rounded-md |
| 5 (20px) | 6px | rounded-sm |
Sizes
| Size | Dimensions | Tailwind | Use For |
|---|---|---|---|
| 12 | 48×48px | size-12 | Profile headers, user cards |
| 10 | 40×40px | size-10 | Navigation, dropdowns |
| 8 | 32×32px | size-8 | Comments, lists (default) |
| 6 | 24×24px | size-6 | Compact lists, mentions |
| 5 | 20×20px | size-5 | Inline, tags |
Styling
Fallback
| Property | Value |
|---|---|
| Background | bg-accent (#e4eefa) |
| Border | border border-accent-border (#c3dbf4) |
| Text Color | text-accent-foreground (#19518b) |
| Font | font-sans (Adelle Sans Regular) |
| Text Align | text-center |
Fallback Text Size by Avatar Size
| Avatar Size | Fallback Text Size | Line Height |
|---|---|---|
| 12 (48px) | text-sm (14px) | leading-5 (20px) |
| 10 (40px) | text-sm (14px) | leading-5 (20px) |
| 8 (32px) | text-sm (14px) | leading-5 (20px) |
| 6 (24px) | text-xs (12px) | leading-4 (16px) |
| 5 (20px) | text-xs (12px) | leading-4 (16px) |
Image Loading State
| Property | Value |
|---|---|
| Background | bg-muted (#f4f4f5) |
States
| State | Implementation |
|---|---|
| Active | Base appearance (default) |
| Focus | Border + ring shadow — scales with avatar size |
Focus State by Size
| Size | Border | Ring Spread | Rounded Radius (Rounded Shape) |
|---|---|---|---|
| 12 (48px) | border border-ring | shadow-[0_0_0_3px] | rounded-2xl (16px) |
| 10 (40px) | border-[0.833px] border-ring | shadow-[0_0_0_2.5px] | rounded-[13.333px] |
| 8 (32px) | border-[0.667px] border-ring | shadow-[0_0_0_2px] | rounded-[10.667px] |
| 6 (24px) | border-[0.5px] border-ring | shadow-[0_0_0_1.5px] | rounded-[8px] |
| 5 (20px) | border-[0.417px] border-ring | shadow-[0_0_0_1.25px] | rounded-[6.667px] |
Focus ring color: ring (#a1a1aa) border with rgba(163,163,163,0.5) shadow. Simplified implementation uses ring-3 ring-ring for consistent focus styling.
Common Patterns
Basic with Fallback (Rounded — default)
<Avatar className="rounded-2xl">
<AvatarImage src="/user.jpg" alt="@username" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
Rounded Shape — All Sizes (size-dependent radius)
// Size 12 — rounded-2xl (16px)
<Avatar className="rounded-2xl">
<AvatarImage src="/user.jpg" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
// Size 10 — rounded-xl (14px)
<Avatar className="size-10 rounded-xl">
<AvatarImage src="/user.jpg" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
// Size 8 — rounded-lg (10px)
<Avatar className="size-8 rounded-lg">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-sm">CN</AvatarFallback>
</Avatar>
// Size 6 — rounded-md (8px)
<Avatar className="size-6 rounded-md">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-xs">CN</AvatarFallback>
</Avatar>
// Size 5 — rounded-sm (6px)
<Avatar className="size-5 rounded-sm">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-xs">CN</AvatarFallback>
</Avatar>
Circle Shape — All Sizes
// Large (48px)
<Avatar className="size-12">
<AvatarImage src="/user.jpg" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
// Default (32px)
<Avatar className="size-8">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-sm">CN</AvatarFallback>
</Avatar>
// Small (24px)
<Avatar className="size-6">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-xs">CN</AvatarFallback>
</Avatar>
// Extra small (20px)
<Avatar className="size-5">
<AvatarImage src="/user.jpg" />
<AvatarFallback className="text-xs">CN</AvatarFallback>
</Avatar>
Fallback with Border
<Avatar>
<AvatarFallback className="bg-accent text-accent-foreground border border-accent-border">
CN
</AvatarFallback>
</Avatar>
Avatar Group (Stacked)
<div className="flex items-center pr-2">
<Avatar className="size-12 border-2 border-background -mr-2">
<AvatarImage src="/user1.jpg" />
<AvatarFallback>U1</AvatarFallback>
</Avatar>
<Avatar className="size-12 border-2 border-background -mr-2">
<AvatarImage src="/user2.jpg" />
<AvatarFallback>U2</AvatarFallback>
</Avatar>
<Avatar className="size-12 border-2 border-background -mr-2">
<AvatarFallback className="bg-accent text-accent-foreground border border-accent-border">
+3
</AvatarFallback>
</Avatar>
</div>
With User Info
<div className="flex items-center gap-3">
<Avatar>
<AvatarImage src="/user.jpg" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<div>
<p className="text-sm font-medium">John Doe</p>
<p className="text-xs text-muted-foreground">john@example.com</p>
</div>
</div>
Component Structure
{/* Rounded shape variant — size 12 (default) */}
<div className="relative size-12 overflow-hidden rounded-2xl">
{/* AvatarImage */}
<img
src="/user.jpg"
alt="User"
className="absolute inset-0 size-full object-cover"
/>
{/* AvatarFallback (shown when image fails/loading) */}
<div className="absolute inset-0 flex items-center justify-center bg-accent border border-accent-border text-sm text-accent-foreground">
CN
</div>
</div>
{/* Rounded shape variant — size 10 */}
<div className="relative size-10 overflow-hidden rounded-xl">
...
</div>
{/* Rounded shape variant — size 8 */}
<div className="relative size-8 overflow-hidden rounded-lg">
...
</div>
{/* Rounded shape variant — size 6 */}
<div className="relative size-6 overflow-hidden rounded-md">
...
</div>
{/* Rounded shape variant — size 5 */}
<div className="relative size-5 overflow-hidden rounded-sm">
...
</div>
{/* Circle shape variant */}
<div className="relative size-12 overflow-hidden rounded-full">
...
</div>
Accessibility
- Built on Radix Avatar — presentational component
- Provide meaningful
alttext onAvatarImage - Fallback text is announced by screen readers
- No keyboard interaction (non-interactive element)
Gotchas
| Problem | Solution |
|---|---|
| Fallback shows briefly before image | Use delayMs prop on AvatarFallback |
| Small avatar text too big | Use text-xs for size-6 and size-5 |
| Group avatars not overlapping | Use -mr-2 on each avatar (negative right margin) |
| Group avatar borders blend in | Add border-2 border-background to each avatar |
| Focus ring not visible | Ensure ring token is defined |
| Rounded shape not correct | Use size-dependent radius: rounded-2xl (12), rounded-xl (10), rounded-lg (8), rounded-md (6), rounded-sm (5) |
| Fallback missing border | Add border border-accent-border to AvatarFallback |
| Circle shape used unintentionally | Rounded is the default for all standard contexts. Circle is opt-in only — apply rounded-full explicitly when required for social/legacy interfaces. |
See Also
- Related Components: Hover Card (profile preview on hover), Badge (status indicator)
- Tokens: Colors — Theme-aware color tokens
Last updated: February 20, 2026