Badge
Display a small indicator relative to another element, commonly used for notification counts, status dots, and labels.
Import
vue
<script setup lang="ts">
import { Badge, BadgeAnchor, BadgeLabel } from '@heroui-vue/vue'
</script>Anatomy
Badge is positioned relative to BadgeAnchor. Plain children are automatically wrapped in BadgeLabel; when no children are provided, the badge renders as a dot indicator.
vue
<template>
<BadgeAnchor>
<Avatar />
<Badge color="danger">5</Badge>
</BadgeAnchor>
</template>Usage
Basic
<template>
<div class="demo-badge-row">
<BadgeAnchor>
<Avatar>
<AvatarImage :src="greenAvatar" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge color="danger" size="sm">5</Badge>
</BadgeAnchor>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="orangeAvatar" alt="AB" />
<AvatarFallback>AB</AvatarFallback>
</Avatar>
<Badge color="accent" size="sm">New</Badge>
</BadgeAnchor>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="blueAvatar" alt="CD" />
<AvatarFallback>CD</AvatarFallback>
</Avatar>
<Badge color="success" placement="bottom-right" size="sm" />
</BadgeAnchor>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const greenAvatar = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const orangeAvatar = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg'
const blueAvatar = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg'
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
</style>Colors
<template>
<div class="demo-badge-row">
<BadgeAnchor
v-for="color in colors"
:key="color"
>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge
:color="color"
size="sm"
/>
</BadgeAnchor>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const colors = ['default', 'accent', 'success', 'warning', 'danger'] as const
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
</style>Sizes
<template>
<div class="demo-badge-row">
<BadgeAnchor
v-for="size in sizes"
:key="size"
>
<Avatar :size="size">
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge
color="danger"
:size="size"
>
5
</Badge>
</BadgeAnchor>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const sizes = ['sm', 'md', 'lg'] as const
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
</style>Variants
primary
secondary
soft
<template>
<div class="demo-badge-stack">
<template
v-for="(variant, index) in variants"
:key="variant"
>
<div class="demo-badge-section">
<h4 class="demo-badge-heading">
{{ variant }}
</h4>
<div class="demo-badge-row">
<BadgeAnchor
v-for="color in colors"
:key="color"
>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge
:color="color"
size="sm"
:variant="variant"
>
5
</Badge>
</BadgeAnchor>
</div>
</div>
<Separator v-if="index < variants.length - 1" />
</template>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor, Separator } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const variants = ['primary', 'secondary', 'soft'] as const
const colors = ['accent', 'default', 'success', 'warning', 'danger'] as const
</script>
<style lang="less">
.demo-badge-stack {
display: flex;
flex-direction: column;
gap: 2rem;
text-align: left;
}
.demo-badge-section {
display: flex;
flex-direction: column;
gap: 1rem;
text-align: left;
}
.demo-badge-heading {
margin: 0;
color: var(--color-muted-foreground);
font-size: 0.875rem;
font-weight: 600;
text-transform: capitalize;
}
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
</style>Placements
<template>
<div class="demo-badge-row demo-badge-row--wide">
<div
v-for="placement in placements"
:key="placement"
class="demo-badge-placement"
>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge
color="accent"
:placement="placement"
size="sm"
/>
</BadgeAnchor>
<span class="demo-badge-label">{{ placement }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const placements = ['top-right', 'top-left', 'bottom-right', 'bottom-left'] as const
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
.demo-badge-row--wide {
gap: 2rem;
}
.demo-badge-placement {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.demo-badge-label {
color: var(--color-muted-foreground);
font-size: 0.75rem;
}
</style>With Content
<template>
<div class="demo-badge-row">
<BadgeAnchor>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge color="danger" size="sm">5</Badge>
</BadgeAnchor>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge color="danger" size="sm">New</Badge>
</BadgeAnchor>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge color="danger" size="sm">99+</Badge>
</BadgeAnchor>
<BadgeAnchor>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge color="accent" size="sm">
<BellIcon />
</Badge>
</BadgeAnchor>
</div>
</template>
<script setup lang="ts">
import { defineComponent, h } from 'vue'
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const BellIcon = defineComponent({
setup() {
return () =>
h(
'svg',
{
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
'stroke-width': '2',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'aria-hidden': 'true',
},
[
h('path', { d: 'M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9' }),
h('path', { d: 'M13.73 21a2 2 0 0 1-3.46 0' }),
],
)
},
})
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
.badge svg {
width: 0.625rem;
height: 0.625rem;
}
</style>Dot Badge
<template>
<div class="demo-badge-row">
<BadgeAnchor
v-for="color in colors"
:key="color"
>
<Avatar>
<AvatarImage :src="avatarUrl" alt="John Doe" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<Badge
:color="color"
placement="bottom-right"
size="sm"
/>
</BadgeAnchor>
</div>
</template>
<script setup lang="ts">
import { Avatar, AvatarFallback, AvatarImage, Badge, BadgeAnchor } from '@heroui-vue/vue'
const avatarUrl = 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg'
const colors = ['accent', 'success', 'warning', 'danger'] as const
</script>
<style lang="less">
.demo-badge-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1.5rem;
}
</style>Styling
Passing Classes
vue
<template>
<BadgeAnchor>
<Avatar />
<Badge class="border-2 border-white" color="danger">
<BadgeLabel class="font-bold">99+</BadgeLabel>
</Badge>
</BadgeAnchor>
</template>CSS Classes
| Class | Description |
|---|---|
.badge | Base badge container |
.badge__label | Label text slot |
.badge-anchor | Positioning wrapper for the anchored element |
.badge--accent | Accent color |
.badge--danger | Danger color |
.badge--default | Default color |
.badge--success | Success color |
.badge--warning | Warning color |
.badge--primary | Filled background variant |
.badge--secondary | Secondary background variant |
.badge--soft | Soft background variant |
.badge--sm | Small size |
.badge--md | Medium size |
.badge--lg | Large size |
.badge--top-right | Top-right placement |
.badge--top-left | Top-left placement |
.badge--bottom-right | Bottom-right placement |
.badge--bottom-left | Bottom-left placement |
API
Badge Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | 'default' | 'accent' | 'success' | 'warning' | 'danger' | 'default' | Color variant |
variant | 'primary' | 'secondary' | 'soft' | 'primary' | Visual style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Badge size |
placement | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-right' | Position relative to BadgeAnchor |
class | string | undefined | Additional classes for the badge root |
BadgeAnchor Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | string | undefined | Additional classes for the anchor wrapper |
BadgeLabel Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | string | undefined | Additional classes for the label |
Slots
| Component | Slot | Description |
|---|---|---|
Badge | default | Text, number, icon, or custom content |
BadgeAnchor | default | Anchored element and badge |
BadgeLabel | default | Label content |