Components › States & feedback › Status › Count badge

Count badge

canon

Outlined count next to a heading, tab or column; accent is the filled tone for a count that must be cleared.

Unified the scoped .cnt copies (F246). A count of zero is not drawn — that is an empty state. AD 5 Sep 2026: the .alert variant was deleted (never called anywhere, and white on --critical is 3.91:1, below AA). section-block.css re-declares the geometry 1px wider than ds.css (min-width 18 vs 16) — latent drift. acrm !4026 (27 Sep 2026): the section header count in SectionBlock and RecordRail now IS the canonical CountBadge (`acrm-count cnt`); the geometry overrides `.sb-h .cnt` and `.rr-sec-h .cnt` were deleted (19×17 → 21×16, padding 6). acrm !4034 (27 Sep 2026, count wave): tab counts (`.acrm-tab`, TabStrip in packages/ui) are CountBadge too; the segment builder toggle count `.sgb-ctl` = NEUTRAL CountBadge (an accent pill would vanish on the toggle's accent-tint on-state); dead `.sgb-tab .count` / `.eml-count` removed in app and mirror; inert `cnt` class names removed (kept only on RecordRail for a test). Intentionally NOT CountBadge: group-heading counts `.tl-grp .cnt` (bare number) and the notification bell overlay.

Used in 10 files · 8 areas · 11× — components/Board, components/FilterBar, components/SectionBlock, components/meetings, components/notifications, components/segment …

Keyboard

  • Not focusable and not interactive: it is a <span> that labels something else.
  • When it sits inside a tab or a nav item, that host is the control and takes the tab stop; the count travels with it.

ARIA

  • No role and no label of its own. The badge is read as part of the thing it annotates — Úkoly 12 — which is the intended reading.
  • It must therefore never be the only place the meaning appears: 12 alone says nothing, so the heading next to it has to carry the noun.
  • Nothing announces a change in the number. A count that goes up in the background is silent, and accent (unread) is exactly the case where that matters.
  • A count that is a problem must say so in words; there is no longer a tone that carries it.

Focus

  • Nothing focusable, so no ring of its own. Inside a tab, the tab's own foundation ring applies.

Contrast

Computed from packages/ui/src/tokens/tokens.css:

  • Default: --fg-secondary on --surface-75 — 3.80:1 light, 6.53:1 dark. Below AA for normal text in the light theme, though it is 11px bold on a bordered ground, and the 1px --border gives the shape its own definition rather than relying on the fill.
  • .accent: --accent-ink on --accent-tint — 4.58:1 light, 5.37:1 dark. AA.
  • .alert was removed on 5 Sep 2026 precisely because it failed here: white on --critical is 3.91:1 in both themes, below AA on the variant meant to shout.

Known limits

  • The default tone is under AA in the light theme; it leans on the border to stay legible.
  • Changes are never announced.
  • The 1px geometry drift between ds.css and ds/section-block.css means the same badge is drawn at two sizes in different parts of the app.

Source: docs/status/count-badge.a11y.md · GitLab