Skip to content

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

John DoeJD5ABABNewCDCD

<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

John DoeJDJohn DoeJDJohn DoeJDJohn DoeJDJohn DoeJD

<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

John DoeJD 5 John DoeJD 5 John DoeJD 5

<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

John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5

secondary

John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5

soft

John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5 John DoeJD 5

<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

John DoeJDtop-right
John DoeJDtop-left
John DoeJDbottom-right
John DoeJDbottom-left

<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

John DoeJD5John DoeJDNewJohn DoeJD99+John DoeJD

<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

John DoeJDJohn DoeJDJohn DoeJDJohn DoeJD

<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

ClassDescription
.badgeBase badge container
.badge__labelLabel text slot
.badge-anchorPositioning wrapper for the anchored element
.badge--accentAccent color
.badge--dangerDanger color
.badge--defaultDefault color
.badge--successSuccess color
.badge--warningWarning color
.badge--primaryFilled background variant
.badge--secondarySecondary background variant
.badge--softSoft background variant
.badge--smSmall size
.badge--mdMedium size
.badge--lgLarge size
.badge--top-rightTop-right placement
.badge--top-leftTop-left placement
.badge--bottom-rightBottom-right placement
.badge--bottom-leftBottom-left placement

API

Badge Props

PropTypeDefaultDescription
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
classstringundefinedAdditional classes for the badge root

BadgeAnchor Props

PropTypeDefaultDescription
classstringundefinedAdditional classes for the anchor wrapper

BadgeLabel Props

PropTypeDefaultDescription
classstringundefinedAdditional classes for the label

Slots

ComponentSlotDescription
BadgedefaultText, number, icon, or custom content
BadgeAnchordefaultAnchored element and badge
BadgeLabeldefaultLabel content

Released under the Apache-2.0 License.