busy-office-ui
Menu

Badge

Status badges for approval states and document statuses. The bare .bo-badge is the neutral tone. Foregrounds use the --bo-color-*-text tokens, which remap in dark mode to stay AA. A badge is decoration for sighted users — the status text itself is the accessible signal, so never encode status as color alone. Not for anything the reader can act on — a badge is a label, and a label that responds to a click is a control wearing the wrong clothes. A filter value the reader can remove is a chip; anything that fires an action is a button. The test is whether removing it would change what the screen does: if yes, it was never a badge.

Tones

Neutral Approved Pending Rejected In review
View code
<span class="bo-badge">Neutral</span>
<span class="bo-badge bo-badge--success">Approved</span>
<span class="bo-badge bo-badge--warning">Pending</span>
<span class="bo-badge bo-badge--danger">Rejected</span>
<span class="bo-badge bo-badge--accent">In review</span>

--type — record-type chip

An inverted-surface tag naming the record a card holds. A rectangle, not a pill; auto-inverts in dark mode.

Purchase Order #4021 Invoice Change Request
View code
<span class="bo-badge bo-badge--type">Purchase Order #4021</span>
<span class="bo-badge bo-badge--type">Invoice</span>
<span class="bo-badge bo-badge--type">Change Request</span>

In a table — the number-one placement

Invoice #AmountStatus
INV-10234$4,208.00Pending
INV-10235$18,940.50Approved
INV-10236$730.25Rejected

A status column of badges next to numeric cells — where badges actually live in an ERP. The tone word IS the text, so the meaning never depends on the hue alone.

Ranked values — priority, severity, risk, ABC class — need no extra channel. Tone says bad, not how much, so the obvious-looking move is an ordinal modifier (--priority, data-rank). It is refused, and the reason is on this page already: the word is the text. "High" and "Low" are themselves the ordinal channel — readable, sortable, translatable, and announced — and the two-channel rule means that word has to be there whatever else you add. A rank glyph would encode the same fact a second time. What would change this: a screen where the user must compare rank across many rows at a glance and reading the words is too slow. Measured across the 27-screen ERP suite, that screen does not exist — 168 badges, none of them ranked (roadmap 151.3).

Quick reference generated

ClassRole
.bo-badge block (root)
.bo-badge--accent variant: accent
.bo-badge--danger variant: danger
.bo-badge--success variant: success
.bo-badge--type variant: type
.bo-badge--warning variant: warning

API generated from CSS

Blocks bo-badge
Variants bo-badge--accentbo-badge--dangerbo-badge--successbo-badge--typebo-badge--warning
Component tokens --bo-badge-bg--bo-badge-border--bo-badge-fg
JS required None — CSS-only.
  • A badge is decoration — the status TEXT is the accessible signal; never encode status as color alone.
Contrast — 33 AA pairs this component uses (generated, CI-gated)
TextonLightDark
text-primary bg-surface 17.74 16.15
text-primary bg-canvas 16.98 18.08
text-secondary bg-surface 10.31 11.46
text-secondary bg-muted 9.37 9.75
text-muted bg-surface 7.56 6.65
text-muted bg-muted 6.87 5.66
bg-surface text-primary 17.74 16.15
accent-text accent-subtle 7.27 8.38
danger-text danger-subtle 5.91 8.06
warning-text warning-subtle 4.84 9.21
success-text success-subtle 4.79 10.17
danger-text bg-surface 6.47 8.89
danger-text bg-canvas 6.19 9.96
success-text bg-surface 5.02 12.02
success-text bg-canvas 4.8 13.46
accent bg-surface 5.47 9.07
text-primary bg-hover 16.12 13.75
text-primary bg-selected 17.01 11.86
text-secondary bg-selected 9.88 8.41
accent-text bg-selected 7.27 8.38
text-primary bg-surface-raised 17.74 14.51
text-secondary bg-canvas 9.86 12.82
border-control bg-surface 4.83 6.65
--bo-state-error-color bg-surface 4.83 6.1
accent accent-subtle 5.25 6.66
border-control bg-muted 4.39 5.66
accent bg-muted 4.97 7.72
warning-strong bg-muted 4.56 6.69
warning-strong bg-surface 5.02 7.86
danger bg-muted 4.39 5.19
text-primary bg-muted 16.12 13.75
success-text bg-muted 4.56 10.23
danger-text bg-muted 5.88 7.57

Maturity generated

Introduced
v0.1.0
CSS floor
Chrome/Edge 99 · Firefox 97 · Safari 15.4
Alignment scored
2026-08-23
Assistive-tech evidence
None recorded

Pin this component's first release with npm i @busy-office/ui@0.1.0. The floor is derived from this component's stylesheet alone — set by @layer — so it sits at or below the whole framework's Chrome/Edge 119 · Firefox 129 · Safari 17.5. No assistive-technology runtime result is recorded for any component: it needs a human listening to VoiceOver and NVDA on owner hardware; no gate in this repo can simulate announcement behaviour. What automation covers instead is test:axe across every page at 1440 and 390, and check:forced-colors — see accessibility.

Design-system alignment generated

100% (15/15) — how closely this component follows the design language. Each rule is scored 0-3 against a checkable citation; rules that don't apply leave the denominator. Scored 2026-08-23.

Rule Score Evidence
Typography 3 / 3 --bo-font-size-xs and a weight token; the 0.05em letter-spacing is intrinsic, same basis as form/combobox
Colour 3 / 3 raw hex only inside @media print, where theme tokens would be wrong on paper; status meaning is carried by TEXT, colour never alone
Spacing 3 / 3 the chip hug and the unconditional 1px boundary both carry their reason; the bare numbers a scan flags are measurements quoted INSIDE the WRAP comment on .bo-badge, not declarations. Corrected 2026-09-04 (Polish round 1 on avatar): this cite used to point at a line number in badge.css, which 249.8's 3-line @tagline header moved underneath it; it names the comment instead, which does not move
Interaction n/a a static span
Content 3 / 3 opener carries the wrong-choice clause: "Not for anything the reader can act on" — a badge is a label; a removable filter value is a chip and anything that fires is a button, with the test stated (would removing it change what the screen does). Blind re-scored 2026-08-23 (Polish round 2), judged genuine: clickable/dismissible badges are a common misuse of a status pill.
Fit 3 / 3 approval states and document statuses; the --type rectangle is scoped to record-type labels
↑↓ move Enter open Esc close