Skip to content
HyperDesign System

Badge

A 20px pill that labels, counts or reports a status. It is not a control: it never takes focus unless it wraps a link. Source: src/components/ui/badge.tsx.

Variants

Ten looks in one size. Secondary carries most of the app; the status hues appear only as a tinted chip with the hue as text.

NewLatest05:00+3BetaConnectedConflictSyncingFailedDocs

When to use each

Badge variants
ExamplePropUsage
NewInk. Loud; reserve it for one marker in a region.
LatestThe workhorse: tags, model names, counts, MCP / Native.
05:00A hairline value that sits beside text, such as a verdict.
+3No fill: overflow counts and quiet metadata in a row.
BetaTangerine tint. A product marker, never a status.
ConnectedStatus: done, healthy, connected.
ConflictStatus: needs a look, but nothing failed.
SyncingStatus: neutral news or work in progress.
FailedStatus: failed or removed.
DocsText-only; pair with asChild around a link.

Status

Success, warning, info and destructive are the four status tones: a 10% fill of the hue with the hue as text. Add the icon so the state reads without colour.

ConnectedConflictSyncingFailed

With icon

Icons render at 12px. Mark them data-icon="inline-start" or "inline-end" and the badge trims that side's padding so the icon sits optically centred.

BetaChangelog

Counts and markers

Figures are tabular, so a count that ticks doesn't shift its neighbours. Kind markers such as MCP take the 12px caps role.

312128+1+9
MCPNative

With asChild around a Link the badge becomes a focusable anchor with a hover fill and the focus ring.

Props

Badge props
PropTypeDefaultDescription
variant"default" | "secondary" | "outline" | "ghost" | "link" | "brand" | "success" | "warning" | "info" | "destructive""default"The look. Mirrored as data-variant.
asChildbooleanfalseRender the single child (usually a Link) with the badge's classes, via Radix Slot.
...propsComponentProps<"span">—Native attributes pass through; className merges last. There is no size prop: every badge is 20px tall, 12px text.

Best practices

When to use

  • Label, count or status of something next to it. If pressing it does something, it is a Button (chip or tint), not a Badge.
  • Default to secondary. Status tones only for a real state; brand only for a product marker such as Beta.
  • Cap a row of badges and show the rest as a ghost +N count, as the trace cards do.

Behavior

  • One or two words. A badge never wraps; long text belongs in a sentence.
  • Add shrink-0 when the badge sits in a row with truncating text, so the badge is never the thing that squeezes.
  • There is no size prop. Need a larger marker? It is probably a Button size="xs" or an Overline.

Accessibility

  • Status needs more than colour: pair the hue with an icon or a word that says the state.
  • Icons inside take aria-hidden; the text is the label.
  • A badge that only repeats nearby text (a struck old value, a decorative count) can take aria-hidden itself.