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.
When to use each
| Example | Prop | Usage |
|---|---|---|
| New | Ink. Loud; reserve it for one marker in a region. | |
| Latest | The workhorse: tags, model names, counts, MCP / Native. | |
| 05:00 | A hairline value that sits beside text, such as a verdict. | |
| +3 | No fill: overflow counts and quiet metadata in a row. | |
| Beta | Tangerine tint. A product marker, never a status. | |
| Connected | Status: done, healthy, connected. | |
| Conflict | Status: needs a look, but nothing failed. | |
| Syncing | Status: neutral news or work in progress. | |
| Failed | Status: failed or removed. | |
| Docs | Text-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.
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.
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.
As link
With asChild around a Link the badge becomes a focusable anchor with a hover fill and the focus ring.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "secondary" | "outline" | "ghost" | "link" | "brand" | "success" | "warning" | "info" | "destructive" | "default" | The look. Mirrored as data-variant. |
| asChild | boolean | false | Render the single child (usually a Link) with the badge's classes, via Radix Slot. |
| ...props | ComponentProps<"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.