Display
Badge
A count or a state, set in mono so it reads as metadata.
Usage
When to reach for it
import { Badge } from '@misoto22/design'Notes
A count, a state, a small inline marker.
Mono and small, so it reads as metadata rather than as content. A badge is not interactive — if it can be clicked or dismissed it is a Tag or a button, and giving this one an onClick produces a control a keyboard cannot reach.
Anatomy
| Element | Description |
|---|---|
| Chiprequired | The <span>: inline-flex on the --radius-sm corner, mono at 12px with wide tracking. The mono face is the whole signal — it is what tells a reader this is metadata rather than a word of the sentence it sits in. |
| Groundrequired | The tone’s fill — --stone for neutral, the soft tint of --ok, --warn or --danger for the three status tones, and nothing at all for outline. |
| Borderrequired | Always drawn, and transparent for every tone but outline, so the box reserves the pixel either way and swapping tone at runtime moves nothing beside it. |
| Contentrequired | children, with a 6px gap between them — so a StatusDot or a Kbd set beside the text spaces itself without a wrapper. |
Best practices
Do
- Leave tone at neutral unless the badge names a STATE: the three status tones are the only chroma this system spends, and a badge that is red because the page wanted red is the thing the scale exists to prevent.
- Reach for outline when the badge sits on --stone already — every other tone fills its own ground, and a neutral badge on stone is a chip with no visible edge at all.
- Keep it to a count, a word, or a short state. It is 12px mono sized for one line, so a phrase in it is prose set in the metadata face and wraps inside a box that was never given a second line.
Don’t
- A row of them is a Tag list drawn in the wrong component: Badge has no active state, so the filter bar it turns into cannot show which facet is on.
- A neutral Badge and an inactive Tag are the same corner, the same padding and the same 12px mono, separated by one ink step — so a row that mixes states and topics reads as one undifferentiated run of chips.
- There is no dismiss affordance here. A × written into children is text inside the accessible name, so the badge is announced as “beta ×” and the close it advertises does not exist.
Examples
tones
Every tone the badge has, with the neutral default first. Leave it at neutral unless the badge names a STATE: the three status tones are the only chroma this system spends, and a badge that is red because the page wanted red is the thing the scale exists to prevent.
with a status dot
A dot inside the chip rather than beside it. Badge spaces its children 6px apart, so a StatusDot needs no wrapper of its own — and the dot is aria-hidden, so the word next to it has to name the state on its own. Reach for this in a table cell where the row already supplies the subject; a state that is the whole line is a StatusPill.
on a stone ground
The same two words on the ground one of them disappears into. Neutral fills itself with --stone and draws a transparent border, so on a stone panel it is a chip with no visible edge at all; outline is the tone that keeps its hairline. Reach for outline whenever the badge sits on a filled surface.
Types
export type BadgeTone = 'neutral' | 'success' | 'warning' | 'danger' | 'outline'Accessibility
- Not interactive. A badge with an onClick is a control a keyboard cannot reach.
- The status tones double their colour with words, so the meaning survives monochrome and colour-blindness.