Keyboard shortcut: Ctrl + K
Get started

Badge

A small count or marker, on its own or pinned to the corner of something else. It is never interactive: what it reports belongs to the element it sits on.

Usage

vue
8
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="8" />
</template>

Examples

Variants

variant fills the badge with the colour (solid, the default) or tints it and writes the content in the colour (soft), for a count that should not draw the eye. A dot is always solid.

vue
8888
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="8" variant="solid" />
  <VBadge :count="8" variant="soft" />
  <VBadge :count="8" variant="solid" tone="danger" />
  <VBadge :count="8" variant="soft" tone="danger" />
</template>

Tones

tone sets the colour: accent, neutral, success, warning or danger.

vue
88888
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="8" tone="accent" />
  <VBadge :count="8" tone="neutral" />
  <VBadge :count="8" tone="success" />
  <VBadge :count="8" tone="warning" />
  <VBadge :count="8" tone="danger" />
</template>

Custom colours

color replaces the tone, given as hex, a CSS colour name or oklch().

vue
8888
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="8" color="#6d28d9" />
  <VBadge :count="8" color="teal" />
  <VBadge :count="8" color="oklch(0.72 0.19 60)" />
  <VBadge :count="8" color="#facc15" />
</template>

Counters

count displays a number. Past 99 it becomes 99+.

vue
34299+
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="3" />
  <VBadge :count="42" />
  <VBadge :count="128" />
</template>

With an icon

icon takes the place of the number, and wins over count when both are given.

vue
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
import { check, close, warning } from 'vectis-ui/icons'
</script>

<template>
  <VBadge :icon="check" tone="success" />
  <VBadge :icon="warning" tone="warning" />
  <VBadge :icon="close" tone="danger" />
</template>

Dot

dot draws 10px of colour with nothing in it, ignoring count and icon.

vue
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge dot />
  <VBadge dot tone="success" />
  <VBadge dot tone="danger" />
</template>

Inline

The default slot provides a target element, beside which the badge is placed.

vue
MessagesDeployment
<script setup lang="ts">
import { VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="4">Messages</VBadge>
  <VBadge dot tone="success">Deployment</VBadge>
</template>

Overlay

overlay pins the badge to a corner of the target instead of placing it beside it.

vue
<script setup lang="ts">
import { VAvatar, VBadge, VIconButton } from 'vectis-ui'
import { notifications } from 'vectis-ui/icons'
</script>

<template>
  <VBadge :count="12" overlay>
    <VIconButton label="Notifications" :icon="notifications" variant="ghost" tone="neutral" />
  </VBadge>

  <VBadge dot tone="success" overlay>
    <VAvatar name="Ada Lovelace" />
  </VBadge>
</template>

Overlay position

overlayPosition moves the overlay corner from the top to the bottom. The horizontal side follows the reading direction.

vue
<script setup lang="ts">
import { VAvatar, VBadge } from 'vectis-ui'
</script>

<template>
  <VBadge :count="7" overlay>
    <VAvatar name="Ada Lovelace" size="lg" />
  </VBadge>

  <VBadge dot tone="success" overlay overlay-position="bottom">
    <VAvatar name="Grace Hopper" size="lg" />
  </VBadge>
</template>

Bordered

bordered draws a 2px ring around the badge, and ringColor sets its colour to match the surface behind it.

vue
<script setup lang="ts">
import { VAvatar, VBadge } from 'vectis-ui'
</script>

<template>
  <div class="tile">
    <VBadge :count="3" overlay bordered ring-color="var(--vectis-color-surface-raised)">
      <VAvatar name="Ada Lovelace" />
    </VBadge>
  </div>

  <div class="tile tile-accent">
    <VBadge :count="3" tone="danger" overlay bordered ring-color="var(--vectis-color-accent)">
      <VAvatar name="Grace Hopper" />
    </VBadge>
  </div>
</template>

<style scoped>
.tile {
  display: flex;
  padding: var(--vectis-space-4);
  border-radius: var(--vectis-radius-surface);
  background: var(--vectis-color-surface-raised);
}
.tile-accent {
  background: var(--vectis-color-accent);
}
</style>

API

Props

PropTypeDefault
variantBadgeVariant'solid' | 'soft''solid'
How strongly the badge is painted: filled with the full colour, or a tinted background with the content in the colour, for a count that should not draw the eye. A dot is always solid, since a pale disc with nothing in it is hard to tell from the page.
toneBadgeTone'neutral' | 'accent' | 'danger' | 'success' | 'warning''accent'
The meaning the badge carries, expressed as a colour. A solid badge is filled with it and its text adapts to stay readable; a soft one is tinted with it and writes its text in it.
colorstringnone
A colour of your own, as hex, a CSS name or oklch(), which replaces the tone. On a solid badge, where contrast-color() is supported the text turns black or white by itself; everywhere else it falls back to white, so with a light colour the contrast is yours to check. A soft badge mixes its background and text from that colour and the theme.
countnumbernone
The number to display. Anything above 99 is shown as 99+, so a busy counter cannot stretch the pill indefinitely.
iconIconSourcenone
A single icon shown instead of a number. It takes precedence over count, and is ignored when the badge is a dot.
dotbooleanfalse
Reduces the badge to a 10px dot with no content, the discreet way to signal that something is new without saying how much.
overlaybooleanfalse
Pins the badge to a corner of the target element instead of placing it beside it. It does nothing when the badge has no target.
overlayPositionBadgeOverlayPosition'top' | 'bottom''top'
Which corner an overlaid badge is pinned to: the top one by default, the bottom one for a marker that belongs at the foot of its target, such as a presence dot under an avatar. The horizontal side follows the reading direction and is not configurable.
borderedbooleanfalse
Draws a 2px ring in the colour of the surface behind the badge, which detaches it from a busy target such as a picture. That colour is the page background by default, and ringColor is how you change it.
ringColorstringnone
The colour of the ring bordered draws. It defaults to the page background, so a badge sitting on a card or a coloured banner should be given that surface's colour instead. Without bordered it does nothing.

Slots

SlotType
default{}
The element the badge belongs to. Without it the badge stands on its own; with it, the badge is placed beside the element, or in its corner under overlay, and is hidden from assistive technology: say the count in the element's own name.

Types

The types the tables above name, written as the library declares them. The ones carrying export can be imported from vectis-ui to type your own code; the others are the shape of what a slot hands out.

export interface BuiltinIcon {
  name: string
  paths: readonly [string] | readonly [string, string]
}
export type IconRender =
  | { path: string; viewBox?: string }
  | { component: Component; props?: Record<string, unknown> }
  | { src: string }
  | { text: string; class?: string }
  | { class: string }
export type IconSource = string | BuiltinIcon | IconRender

CSS variables

TokenValue
--vectis-control-size-badge-h1.25rem
--vectis-control-size-badge-dot0.625rem
--vectis-control-size-badge-ring2px