Badge
Migration guide for Badge from HeroUI v2 to v3
Refer to the v3 Badge documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
Structure Changes
In v2, Badge was a wrapper component that positioned content relative to its children:
import { Badge, Avatar } from "@heroui/react";
export default function App() {
return (
<Badge content="5" color="primary">
<Avatar src="https://i.pravatar.cc/300" />
</Badge>
);
}In v3, Badge uses a compound component pattern with Badge.Anchor for positioning:
import { Badge, Avatar } from "@heroui/react";
export default function App() {
return (
<Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
<Badge color="accent">5</Badge>
</Badge.Anchor>
);
}Key Changes
1. Component Structure
v2: Single Badge component wrapping children, with content prop for badge text
v3: Compound components: Badge.Anchor (positioning wrapper), Badge (the badge itself), Badge.Label (text slot, auto-wrapped for strings)
2. Variants
v2: solid, flat, faded, shadow
v3: primary, secondary, soft
3. Colors
v2: default, primary, secondary, success, warning, danger
v3: default, accent, success, warning, danger
4. Prop Changes
| v2 Prop | v3 Location | Notes |
|---|---|---|
content | Badge children | Content is now passed as children |
children | Badge.Anchor | The anchored element goes inside Badge.Anchor |
variant | Badge | Values changed (see variant mapping) |
color | Badge | primary → accent, secondary removed |
size | Badge | Same (sm, md, lg) |
placement | Badge | Same (top-right, top-left, bottom-right, bottom-left) |
shape | - | Removed (use Tailwind CSS) |
showOutline | - | Removed (use Tailwind CSS e.g. border-2) |
disableOutline | - | Removed |
disableAnimation | - | Removed |
isInvisible | - | Removed (use conditional rendering) |
isOneChar | - | Removed (use Tailwind CSS) |
isDot | - | Omit children to render as dot |
classNames | - | Use className on individual components |
5. Variant Mapping
| v2 Variant | v3 Equivalent | Notes |
|---|---|---|
solid | primary | Filled background |
flat | soft | Light background |
faded | secondary | Border with background |
shadow | primary | Use Tailwind shadow-* classes |
6. Color Mapping
| v2 Color | v3 Equivalent | Notes |
|---|---|---|
default | default | Same |
primary | accent | Renamed |
secondary | default or accent | Depends on context |
success | success | Same |
warning | warning | Same |
danger | danger | Same |
Migration Examples
Basic Badge
import { Badge, Avatar } from "@heroui/react";
<Badge content="5" color="primary">
<Avatar src="https://i.pravatar.cc/300" />
</Badge>import { Badge, Avatar } from "@heroui/react";
<Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
<Badge color="accent">5</Badge>
</Badge.Anchor>Dot Badge
<Badge content="" isDot color="success">
<Avatar src="https://i.pravatar.cc/300" />
</Badge><Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
<Badge color="success" />
</Badge.Anchor>Placement
<Badge content="5" placement="bottom-right" color="danger">
<Avatar src="https://i.pravatar.cc/300" />
</Badge><Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
<Badge placement="bottom-right" color="danger">5</Badge>
</Badge.Anchor>Visibility Toggle
const [isInvisible, setIsInvisible] = useState(false);
<Badge content="5" isInvisible={isInvisible} color="danger">
<Avatar src="https://i.pravatar.cc/300" />
</Badge>const [isVisible, setIsVisible] = useState(true);
<Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
{isVisible && <Badge color="danger">5</Badge>}
</Badge.Anchor>With Icon Content
import { Icon } from "@iconify/react";
<Badge content={<Icon icon="gravity-ui:check" />} color="success">
<Avatar src="https://i.pravatar.cc/300" />
</Badge>import { Icon } from "@iconify/react";
<Badge.Anchor>
<Avatar>
<Avatar.Image src="https://i.pravatar.cc/300" alt="User" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar>
<Badge color="success">
<Icon icon="gravity-ui:check" />
</Badge>
</Badge.Anchor>Styling Changes
v2: classNames Prop
<Badge
classNames={{
base: "custom-base",
badge: "custom-badge"
}}
/>v3: Direct className Props
<Badge.Anchor className="custom-anchor">
<Avatar />
<Badge className="custom-badge">
<Badge.Label className="custom-label">5</Badge.Label>
</Badge>
</Badge.Anchor>Component Anatomy
The v3 Badge follows this structure:
Badge.Anchor (positioning wrapper)
├── [Anchored element: Avatar, Button, etc.]
└── Badge (the badge indicator)
└── Badge.Label (auto-wrapped for string/number children)Summary
- Component Structure:
Badgewrapping children →Badge.Anchor+Badgeas siblings - Content Prop Removed:
contentprop → pass content asBadgechildren - Dot Badge:
isDotprop → omit children - Visibility:
isInvisibleprop → conditional rendering - Variants Reduced: From 4 to 3 variants (
primary,secondary,soft) - Color Changes:
primary→accent,secondaryremoved - Removed Props:
shape,showOutline,disableAnimation,isOneChar— use Tailwind CSS - ClassNames Removed: Use
classNameon individual compound components