Badge

A compact label for counts, statuses, and tags.

Default

A bare .badge sits on the neutral interactional fill. Use for non-semantic chips like counts or tags.

Default
<span class="badge">Default</span>

Filled intents

Add an intent modifier for a solid filled chip. Each intent ships with its paired -foreground, so a runtime token override recolors the chip and the label together.

Primary Success Warning Danger Info
<div class="demo-row">
  <span class="badge badge--primary">Primary</span>
  <span class="badge badge--success">Success</span>
  <span class="badge badge--warning">Warning</span>
  <span class="badge badge--danger">Danger</span>
  <span class="badge badge--info">Info</span>
</div>

Soft

Add .badge--soft for a tinted chip. The background mixes the intent at 15% over transparent; the label keeps the solid intent color. Without an intent, soft falls back to a muted neutral chip.

Default Primary Success Warning Danger Info
<div class="demo-row">
  <span class="badge badge--soft">Default</span>
  <span class="badge badge--soft badge--primary">Primary</span>
  <span class="badge badge--soft badge--success">Success</span>
  <span class="badge badge--soft badge--warning">Warning</span>
  <span class="badge badge--soft badge--danger">Danger</span>
  <span class="badge badge--soft badge--info">Info</span>
</div>

With icon

Drop a direct <svg> or <i> child. The icon picks up the text color and scales to the badge's font size.

Active Pending Failed Featured
<div class="demo-row">
  <span class="badge badge--soft badge--success">
    <i data-lucide="check"></i>
    Active
  </span>
  <span class="badge badge--soft badge--warning">
    <i data-lucide="clock"></i>
    Pending
  </span>
  <span class="badge badge--soft badge--danger">
    <i data-lucide="x"></i>
    Failed
  </span>
  <span class="badge badge--primary">
    <i data-lucide="star"></i>
    Featured
  </span>
</div>

Loading

Slot a .spinner.spinner--sm in to signal in-flight work. It inherits the badge's text color and shrinks to the badge's font size.

Syncing Loading Uploading
<div class="demo-row">
  <span class="badge badge--soft badge--primary">
    <span class="spinner spinner--sm" role="status" aria-hidden="true"></span>
    Syncing
  </span>
  <span class="badge badge--soft">
    <span class="spinner spinner--sm" role="status" aria-hidden="true"></span>
    Loading
  </span>
  <span class="badge badge--info">
    <span class="spinner spinner--sm" role="status" aria-hidden="true"></span>
    Uploading
  </span>
</div>

In buttons

Drop a badge inside a button for a count or status.

<div class="demo-row">
  <button type="button" class="btn btn--primary">
    Inbox
    <span class="badge">4</span>
  </button>
  <button type="button" class="btn btn--outline btn--neutral">
    Notifications
    <span class="badge badge--danger">12</span>
  </button>
</div>

Customization

Nine variables retune .badge without touching component CSS. Override on .badge itself, on a parent scope, or on :root. The cascade scopes the change.

Variable Default Use
--badge-radius 9999px Corner radius (pill; opts out of --st-radius)
--badge-min-height calc(1.375rem * var(--st-density)) Minimum height; pill adapts to content above this
--badge-padding-y calc(0.125rem * var(--st-density)) Vertical padding
--badge-padding-x calc(0.5rem * var(--st-density)) Horizontal padding
--badge-font-size 0.75rem Label size
--badge-font-weight 500 Label weight
--badge-tone var(--st-muted-foreground) Color source the soft variant tints over; intents reassign this
--badge-bg var(--st-neutral) Background; intents set the intent color, soft mixes 15% over --badge-tone
--badge-color var(--st-neutral-foreground) Label color; intents flip to the paired -foreground; soft reads --badge-tone

Pill is intentional, so the badge opts out of --st-radius. Override --badge-radius per-component if a square chip is genuinely wanted.