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 '@rysinal/heroui-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 '@rysinal/heroui-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 '@rysinal/heroui-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 '@rysinal/heroui-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 '@rysinal/heroui-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-stack .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 '@rysinal/heroui-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 '@rysinal/heroui-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 '@rysinal/heroui-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.