Live preview

Rendered from the tier-2 component tokens + foundation tokens per this spec — a spec-faithful rendering, not the production component (those live in each product repo). Variants and states come from the spec below.

RecommendedHalf dayOpen · 12 spotsWaitlistAlmost fullComing soon

Anatomy

root
The pill: rounded-pill shape, tinted background, compact padding.
label
The text — uppercase, caps tracking, small size, semibold.
dot
Optional leading status dot (e.g. green for Open) coloured by the tone accent.

Token bindings

Each binding's value is resolved live from the built @beestera/tokens output — tier-2 component tokens (--badge-*) collapse through the foundation tier.

Part Property Token Resolved Applies to
root border-radius --badge-radius 9999px --badge-radius → --radius-pill
root background --badge-bg #fafafa --badge-bg → --color-surface-alt tone:neutral
label color --badge-fg #3d3d3d --badge-fg → --color-muted tone:neutral
label font-size --badge-text 0.75rem --badge-text → --text-small
label letter-spacing --badge-tracking 0.06em --badge-tracking → --tracking-caps
root background --color-brand #ffd700 tone:brand
label color --color-ink #181818 tone:brand
root border-color --color-success #178640 tone:success
root border-color --color-danger #dc2626 tone:danger
root border-color --color-warning #a26807 tone:warning
root border-color --color-info #1a6df4 tone:info
label color --color-ink #181818 tone:success

Variants

tone brandneutralsuccessdangerwarninginfo
Semantic tone. brand = yellow fill with ink label; neutral = surface-alt fill; status tones (success/danger/warning/info) are a tinted surface-alt with an ink label and a coloured accent border, keeping label contrast AA.

State matrix

default
Static label — the badge is non-interactive by default.

Accessibility

Role
none (decorative label). If it conveys status not otherwise in text, expose it via an accessible name.
Contrast
Label vs background >= 4.5:1 (WCAG AA text). Status tones keep an ink label on a tinted background; the saturated semantic colour is reserved for the border/dot, never the label text.
Focus order
Not focusable when static. Filter-chip usage (interactive) is a separate concern and MUST be a real control.
Target size
n/a for static badges.

Usage

Do

  • Use tone to signal meaning (success = Open, danger = Waitlist/urgent, neutral = metadata).
  • Keep labels to 1-3 words.
  • Pair a status dot with tone for at-a-glance scanning where space allows.

Don't

  • Don't put long sentences in a badge.
  • Don't colour the label with the saturated semantic token (fails contrast).
  • Don't reuse the static badge as a clickable filter chip without making it a real button.

Implementations

swarm-os
packages/ui/src/Badge.tsbuildBadgeView Ships tone: brand|neutral|success|danger|warning|info. Status tones use bg-surface-alt + text-ink + a coloured border, matching this spec.

Figma source: Component / Badge / Availability