Avatar
Migration guide for Avatar from HeroUI v2 to v3
Refer to the v3 Avatar documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
Structure Changes
In v2, Avatar was a single component that accepted props for image source, name, fallback, and other elements:
import { Avatar } from "@lenso/ui";
export default function App() { return ( <Avatar src="https://example.com/avatar.jpg" name="John Doe" showFallback /> );}In v3, Avatar uses a compound component pattern with explicit subcomponents:
import { Avatar } from "@lenso/ui";
export default function App() { return ( <Avatar> <Avatar.Image src="https://example.com/avatar.jpg" alt="John Doe" /> <Avatar.Fallback>JD</Avatar.Fallback> </Avatar> );}Key Changes
1. Component Structure
v2: Single Avatar component with props
v3: Compound components: Avatar, Avatar.Image, Avatar.Fallback
2. Prop Changes
| v2 Prop | v3 Location | Notes |
|---|---|---|
src | Avatar.Image | Use <Avatar.Image src="..." /> |
name | - | Generate initials and pass to <Avatar.Fallback /> |
showFallback | - | Removed (fallback shown if image fails or not provided) |
fallback, icon | Avatar.Fallback | Place content in <Avatar.Fallback /> |
color | Avatar | Same; primary → accent, secondary → default |
variant | Avatar | New in v3; "default" | "soft" |
size | Avatar | Same |
isBordered | - | Removed (use Tailwind e.g. ring-2 ring-background) |
radius | - | Removed (use Tailwind e.g. rounded-full) |
isDisabled, isFocusable | - | Removed (use Tailwind / asChild if needed) |
getInitials | - | Generate initials manually |
ImgComponent, imgProps | - | Use asChild on Avatar.Image if needed |
onError | Avatar.Image | Use onError on <Avatar.Image /> |
| - | Avatar.Image | New: srcSet, sizes, loading for responsive images |
| - | Avatar.Fallback | New: delayMs to delay fallback display (prevents flash) |
classNames | - | Use className on parts |
| AvatarGroup | AvatarGroup | Available again — compound Avatar children with max / color / variant / isGrid / overlap (clip|ring) and optional AvatarGroup.Count; v2 total → explicit Count; see AvatarGroup |
3. Variant Prop (New in v3)
v2: No variant prop; styling controlled only through color
v3: New variant prop with "default" and "soft" options. The "soft" variant applies a lighter background style.
<Avatar variant="soft" color="accent"> <Avatar.Image src="..." alt="User" /> <Avatar.Fallback>JD</Avatar.Fallback></Avatar>4. Avatar.Image Responsive Attributes (New in v3)
v2: Limited to src and onError
v3: Avatar.Image now supports srcSet, sizes, and loading for responsive image handling
<Avatar> <Avatar.Image src="avatar-400.jpg" srcSet="avatar-200.jpg 200w, avatar-400.jpg 400w" sizes="(max-width: 600px) 200px, 400px" loading="lazy" alt="User" /> <Avatar.Fallback>JD</Avatar.Fallback></Avatar>5. Avatar.Fallback delayMs Prop (New in v3)
v2: Fallback shown immediately or controlled via showFallback
v3: Avatar.Fallback supports a delayMs prop to delay rendering, preventing flash of fallback content when images load quickly
<Avatar> <Avatar.Image src="..." alt="User" /> <Avatar.Fallback delayMs={600}>JD</Avatar.Fallback></Avatar>6. Image and Fallback Handling
v2: Used src, name, showFallback, and fallback props
v3: Must explicitly render <Avatar.Image /> and <Avatar.Fallback /> components
7. Color Props
| v2 Color | v3 Color | Notes |
|---|---|---|
default | default | Same |
primary | accent | Renamed |
secondary | default | Use default color |
success | success | Same |
warning | warning | Same |
danger | danger | Same |
8. AvatarGroup (Available in v3)
v2: Dedicated AvatarGroup with props like isBordered, max, and total
v3: AvatarGroup is available again as a dedicated component. Wrap compound Avatar children, inherit size / color / variant via context, and use max, isGrid, and overlap ("clip" default, or "ring"). v2 total is removed — render an explicit AvatarGroup.Count child for a known server total (it suppresses the auto count from max). isBordered is removed; use Tailwind or overlap="ring". See the AvatarGroup docs.
import { Avatar, AvatarGroup } from "@lenso/ui";
<AvatarGroup max={3} size="md"> <Avatar> <Avatar.Image src="https://example.com/1.jpg" alt="User 1" /> <Avatar.Fallback>U1</Avatar.Fallback> </Avatar> <Avatar> <Avatar.Image src="https://example.com/2.jpg" alt="User 2" /> <Avatar.Fallback>U2</Avatar.Fallback> </Avatar> <Avatar> <Avatar.Image src="https://example.com/3.jpg" alt="User 3" /> <Avatar.Fallback>U3</Avatar.Fallback> </Avatar> <Avatar> <Avatar.Image src="https://example.com/4.jpg" alt="User 4" /> <Avatar.Fallback>U4</Avatar.Fallback> </Avatar></AvatarGroup>Migration Examples
Sizes and Colors
<Avatar size="md" color="primary" src="..." name="John" />Custom Fallback
import { Icon } from "@iconify/react";
<Avatar src="https://broken-url.com/image.jpg" showFallback fallback={<Icon icon="mdi:account" />}/>Avatar Group
import { Avatar, AvatarGroup } from "@lenso/ui";
<AvatarGroup isBordered> <Avatar src="https://example.com/1.jpg" /> <Avatar src="https://example.com/2.jpg" /> <Avatar src="https://example.com/3.jpg" /></AvatarGroup>Avatar Group with Max Count
import { Avatar, AvatarGroup } from "@lenso/ui";
<AvatarGroup max={3}> <Avatar src="https://example.com/1.jpg" /> <Avatar src="https://example.com/2.jpg" /> <Avatar src="https://example.com/3.jpg" /> <Avatar src="https://example.com/4.jpg" /> <Avatar src="https://example.com/5.jpg" /></AvatarGroup>Avatar Group Total → Count
import { Avatar, AvatarGroup } from "@lenso/ui";
<AvatarGroup max={3} total={12}> <Avatar src="https://example.com/1.jpg" /> <Avatar src="https://example.com/2.jpg" /> <Avatar src="https://example.com/3.jpg" /></AvatarGroup>Variants
{/* v2 doesn't have variants, but uses color prop */}<Avatar color="primary" name="John" />Styling Changes
v2: classNames Prop
<Avatar classNames={{ base: "custom-base", img: "custom-img", fallback: "custom-fallback" }}/>v3: Direct className Props
<Avatar className="custom-base"> <Avatar.Image className="custom-img" src="..." alt="..." /> <Avatar.Fallback className="custom-fallback"> JD </Avatar.Fallback></Avatar>Component Anatomy
The v3 Avatar follows this structure:
Avatar (Root) ├── Avatar.Image (optional) └── Avatar.Fallback (optional; shown when image fails or not provided)Helper Function for Initials
Since v3 doesn't have a name prop, you'll need to generate initials manually:
function getInitials(name: string): string { return name .split(" ") .map(n => n[0]) .join("") .toUpperCase() .slice(0, 2);}
// Usage<Avatar> <Avatar.Fallback>{getInitials("John Doe")}</Avatar.Fallback></Avatar>Summary
- Component Structure: Must use compound components (
Avatar.Image,Avatar.Fallback) - Name Prop Removed: Generate initials manually
- ShowFallback Removed: Fallback always shows if image fails
- Variant Prop Added: New
variantprop ("default"|"soft") for visual style control - Responsive Image Support:
Avatar.Imagenow supportssrcSet,sizes, andloadingattributes - Fallback Delay:
Avatar.FallbacksupportsdelayMsto prevent flash of fallback content - Color Mapping:
primary→accent,secondary→default - Bordered Removed: Use Tailwind
ring-2 ring-backgroundclasses - Radius Removed: Use Tailwind
rounded-*classes - Disabled Removed: Use Tailwind
opacity-50classes - AvatarGroup Available: Use the dedicated
AvatarGroupcomponent (docs) with compoundAvatarchildren,max/overlap/isGrid, and optionalAvatarGroup.Count(replaces v2total) - Icon Prop Removed: Place icon content in
Avatar.Fallback - ClassNames Removed: Use
classNameprops on individual components