Badge

A small count, label, or category tag.

Badge annotates something else — a tab, a list row, a nav item, a card. It is never the subject of a view on its own.

Variants

Count

3
<Badge variant="count">3</Badge>

Two-digit count

24
<Badge variant="count">24</Badge>

Label

New
<Badge variant="label">New</Badge>

Tag

DeFiLending
<div className="flex gap-2">
<Badge variant="tag">DeFi</Badge>
<Badge variant="tag">Lending</Badge>
</div>

count is the default. It is sized for a number and stays circular at a single digit. label takes a short word. tag is a 24px uppercase category tag with a small corner radius, as on the app cards of base.org's ecosystem page.

Inverse tone

Draft

<div className="relative h-32 w-56 rounded-3 bg-bds-gray-30">
<Badge variant="label" tone="inverse" className="absolute left-3 top-3">
  Draft
</Badge>
</div>

Set tone="inverse" to draw a dark pill with light text, for a badge laid over an image or video, such as a draft label on a blog card's cover. The fill stays dark in both light and dark themes, so the badge reads against any picture. tone works with every variant; default keeps the secondary fill.

When to use

Use Badge to attach a count, or a one-word label like "New", to another element — a tab, a nav item, a list row. Use the tag variant to show the category of an item, such as an app card's category and subcategory. Tags are display only: they render a span and do not respond to press or focus.

Use something else when:

  • Something is new but there is nothing to count. Use Unread.
  • The label reports the state of a resource. Use Status.
  • People pick or filter by the tag. Use Tag Group, which is built for selectable chips. A Badge is display only.

Usage

Do

Cap large counts at a threshold — 99+ reads faster than 1,284 and keeps the badge from resizing the thing it is attached to.

Don't

Use a label badge as a status indicator. Use Status, which pairs a semantic colour with a distinct icon per state.

Do

Keep tags to one or two words. They are uppercase and never wrap, so a long tag pushes the rest of the row aside.

Don't

Make a tag pressable to filter a list. A Badge has no press or focus states; a selectable chip needs a component built for selection.

Props

PropTypeDefault
tone

`inverse` draws a dark pill with light text, for a badge over media.

Type"default" | "inverse" | nullDefaultdefault
variant

`count` for a number, `label` for a short word, `tag` for a category.

Type"label" | "count" | "tag" | nullDefaultcount

Accessibility

A badge is decorative markup around text, so the text itself must make sense out of context. "3" alone tells a screen reader nothing — put the meaning in the element the badge annotates, for example aria-label="Notifications, 3 unread".

Counts use tabular numerals, so the badge keeps its width as the number changes, and the label never wraps onto a second line.

The text meets 4.5:1 contrast against the badge background in light and dark themes.

A tag is not interactive. It is not focusable and has no role, so a screen reader reads its text inline with the rest of the card. The uppercase is a CSS transform: write the tag text in normal case ("DeFi", not "DEFI") so screen readers do not spell it out letter by letter.