Badge
Usage
Use a badge to label the status of an object (a vehicle "In service", a work order "Overdue") or a count ("7"). Badges are read-only; for filters use tags, for page-level messages use an alert.
- Neutral — states with no urgency: "Parked", "Draft".
- Info — scheduled or pending: "Scheduled", "Awaiting parts".
- Success — healthy: "In service", "Passed inspection".
- Warning — needs attention soon: "Due in 3 days".
- Danger — blocking or late: "Overdue", "Failed inspection".
- Count — a number; cap at "99+". Dot — "something new" when the number doesn't matter.
Content: one or two words, sentence case, with a number when it helps ("Due in 3 days"). Keep the vocabulary fixed across the product so "Overdue" always means the same thing.
Anatomy
- Container —
<span class="badge badge--{tone}"> - Icon (tones) —
svg.badge__icon, a different shape per tone,aria-hidden - Dot (optional) —
.badge__dotinstead of an icon - Label — the status word or count
- Anchor (optional) —
.badge-anchorpins a count or dot to the corner of a control
Examples
States marked hover and focus-visible are frozen with .is-hover and .is-focus-visible. Those classes share their rule with the real pseudo-class; never use them in product code.
Badge
Each tone pairs a contrast-checked feedback color with a distinct icon shape and a word.
<span class="badge badge--danger">
<svg class="badge__icon" aria-hidden="true" focusable="false"><use href="#icon-octagon-alert"></use></svg>Overdue
</span>
<span class="badge badge--neutral"><span class="badge__dot"></span>Parked</span>
<!-- Count on a control: the number is in the control's name too -->
<span class="badge-anchor">
<button type="button" class="btn btn--secondary" aria-describedby="overdue-count">Overdue services</button>
<span class="badge badge--count" id="overdue-count">7</span>
</span>
API
| Hook | Values | Purpose |
|---|---|---|
.badge | block class | Pill; neutral by default |
.badge--neutral | --info | --success | --warning | --danger | modifier class | Tone → color.feedback.* fg/bg/border |
.badge--count | modifier class | Solid inverse pill for numbers |
.badge--dot | modifier class | Text-less dot; the parent carries the meaning |
.badge__icon | __dot | part classes | Leading shape |
.badge-anchor | wrapper class | Positions a count/dot on a button's corner |
Do and don't
"Due in 3 days"
Badges as buttons or filters
Accessibility
Badges are static text; they are not focusable and have no keyboard behavior.
- Status is never color alone: the label says it and each tone has its own icon shape (circle-check, info, triangle, octagon).
- Count and dot badges on a control: put the meaning in the control's accessible name ("Notifications, new updates") or link the count with
aria-describedby; hide the visual badge witharia-hiddenwhen the name already says it. - Live counts: announce changes through a
role="status"region, not by making the badge live. - Contrast: every tone uses
color.feedback.{tone}.fgoncolor.feedback.{tone}.bg, checked at 4.5:1 in light, dark and high-contrast; count usestext.inverseonbg.inverse. - Forced colors: badges keep a
CanvasTextborder; dots render asCanvasText.
Tokens
| Custom property | Purpose |
|---|---|
--color-feedback-{info|success|warning|danger}-{bg|fg|border|icon} | Tone colors (contrast-checked fg/bg) |
--color-bg-subtle, --color-text-default, --color-border-default | Neutral tone |
--color-bg-inverse, --color-text-inverse | Count badge |
--radius-full | Pill shape |
--font-size-xs, --font-weight-semibold | Label |
--icon-size-sm | Tone icon |