Design System /Components /Chips & Badge

Chips & Badge

Small labels for state, category, and count. They describe — they never decorate.

Playground

Pick a tone, size, and configuration. The specimen and snippet update in lockstep.

Live Preview Flip Props
State
Default
Height
32 px
Radius
9999px
Type
13/18

Usage

Chips and badges describe — they never decorate.

Reach for a chip when you need to surface a piece of metadata about an object: a category, a state, a tag, a filter. Reach for a badge when you need to count something — unread, unseen, or new. Use a status pip for service health. Never decorate a card with a chip just to add color.

Types

Tonal chips

Each tonal pairs a tint with a deep label. AA at 13px.

Default Action Scanning Protected Exposed Review Pro Draft

With leading dot

Use the dot to reinforce the tonal — never decoratively.

Active Pending Failed

Removable

For filters and user-applied tags. Always include an aria-label on the close button.

Tag: aliases filter: this week

Badges

For unread counts and unseen alerts. Numbers only — no text.

Inbox 3 Alerts 12 Pro 99+ New

Status pips

Service health and persistent state. The live variant pulses; nothing else should.

Active Pending Failed Paused

Sizes

Small for dense tables, default everywhere else, large for hero callouts.

Small Default Large

States

Chips are mostly static. Removable chips have a hover state on the close button only.

DefaultDefault
HoverHover (interactive only)
FocusFocus
DisabledDisabled

Dimensions

Height24 sm · 28 default · 32 lg
Padding10 px horizontal · 5 px vertical (default)
Radius9999px — always pill
Gap (icon ↔ text)6 px
Leading dot6 × 6 px · 50% radius
Close icon (removable)10 × 10 px · stroke 2.5

Badge counts

Min size18 × 18 px
Padding0 × 5 px
Radius9999px
Dot variant8 × 8 px · no padding
MaxShow 99+ for counts > 99

Typography

Chip · defaultSTK Bureau Sans · 500 · 13/13
Chip · smallSTK Bureau Sans · 500 · 12/12
Chip · largeSTK Bureau Sans · 500 · 14/14
Badge countSTK Mono · 600 · 11/11
StatusSTK Bureau Sans · 500 · 14/14

Color styles

Each tonal pairs a tint background with a deep label. All combinations pass AA at 13px.

Default--bg-muted + --fg-default
Firey · action#FFDBCC + #B33A00
Blue · info--brand-100 + #2A3BA8
Green · success#D6F3DD + #006622
Red · exposed#FADBDB + #8C1E1E
Amber · review#FFEDC7 + #855700
Ink · premium#000000 + #FFFFFF
Outline · drafttransparent + --border-strong + --fg-default

Status pips

Live#009933 · pulses 1.6s loop
Warn#E6A500
Down#C53535
Idle--border-strong

Spacing

Chip cluster gap810 px
Chip ↔ adjacent text6 px
Badge inline offset6 px after the noun
Status pip ↔ label8 px

Tone carries meaning

Protected Review Exposed
Do

Use tone consistently — green is success, amber is review, red is risk. Don't break the mapping.

Pro Featured New
Don't

Don't use tonals to color-code categories. Mixed signals make every chip noise.

Don't decorate

A chip should always be load-bearing. If removing it doesn't change what the user understands, it's decoration — delete it.

Whitepages exposure
Active
Do

The chip tells you something the title doesn't — current state.

Whitepages exposure
data broker
Don't

"Whitepages" already implies data broker. The chip is decoration.

Don't over-stack

Three chips on one row is a maximum. Past that, the eye stops parsing them — they collapse into "stuff."

Activealiasesthis week
Do

Three chips, three distinct dimensions: state, category, time.

Activealiasesworkimportanturgentstarred
Don't

Six chips is noise. Pick the two that matter most for this view.

Accessibility

  • Don't rely on color alone — pair the tonal with text or an icon.
  • Removable chips: the close button needs an aria-label describing what's being removed.
  • Live status pip: add role="status" and a visually-hidden text label.
  • Badge counts need a screen-reader label: "Inbox, 3 unread."
  • All tonal combinations pass WCAG AA at 13px.

HTML

<!-- Default chip -->
<span class="chip">Whitepages</span>

<!-- Tonal + leading dot -->
<span class="chip green dot">Active</span>

<!-- Removable -->
<span class="chip removable">
  Tag: aliases
  <button aria-label="Remove tag"><svg>...</svg></button>
</span>

<!-- Badge count -->
Inbox <span class="badge-count">3</span>

<!-- Status pip -->
<span class="status live" role="status">
  <span class="swatch"></span>Protection active
</span>

React

<Chip tone="green" leadingDot>Active</Chip>
<Chip removable onRemove={handleRemove}>aliases</Chip>
<Badge count={3} />
<Status tone="live">Protection active</Status>

Props

  • tone"default" | "firey" | "blue" | "green" | "red" | "amber" | "ink" | "outline"
  • size"sm" | "md" | "lg"
  • leadingDot — boolean, reinforces tonal
  • removable — adds close button
  • onRemove — fires on close click
  • icon — optional leading icon (use sparingly)
  • Badge: count, tone ("accent" | "ink" | "subtle")
  • Status: tone ("live" | "warn" | "down" | "idle")

CSS tokens

--chip-radius: 9999px;
--chip-padding-x: 10px;
--chip-padding-y: 5px;
--chip-gap: 6px;

/* tonal mapping */
--chip-green-bg: #D6F3DD;
--chip-green-fg: #006622;
--chip-amber-bg: #FFEDC7;
--chip-amber-fg: #855700;
--chip-red-bg:   #FADBDB;
--chip-red-fg:   #8C1E1E;