Badge
Compact inline label — pill or rectangle, uppercase, six colour variants, three sizes, optional status dot, and full radius control. Use it to flag state (New, Beta, Hot), count things (12 unread), tag entities (EU · Pro), or call out a fresh release.
Variants
Six visual styles cover the common semantic palette: default (a quiet outlined pill), solid (the loud monochrome stamp), green / yellow / red (semantic status), and soft (a neutral grey for ambient meta info).
<Badge>Default</Badge>
<Badge variant="solid">Solid</Badge>
<Badge variant="green">New</Badge>
<Badge variant="yellow">Beta</Badge>
<Badge variant="red">Hot</Badge>
<Badge variant="soft">Soft</Badge>Choosing a variant
green— positive state, successful action, "new" or "live".yellow— warning state, "beta", "in progress", "pending".red— error, blocking state, "hot", urgent count.solid— high-emphasis meta label (versions, "live"), used sparingly to avoid visual noise.soft— quiet neutral tag for filters, categories, or auxiliary info.default— the bare outlined pill; safe choice when no semantic tone fits.
Sizes
Three sizes — sm (4 × 10 px, 11 px text), md (default — 6 × 14 px, 12.5 px text), lg (8 × 18 px, 14 px text). Reach for sm when the badge sits inline with body copy or as a nav-item indicator; reserve lg for hero areas where the badge is the focal element.
<Badge size="sm">Small</Badge>
<Badge>Medium</Badge>
<Badge size="lg">Large</Badge>Status dot
Pass the dot boolean to render a small leading dot in the badge's foreground colour. This is the canonical status-indicator pattern — pair it with a colour variant that matches the state and keep the label short.
<Badge dot variant="green">Online</Badge>
<Badge dot variant="yellow">Idle</Badge>
<Badge dot variant="red">Offline</Badge>
<Badge dot variant="soft">Draft</Badge>
<Badge dot variant="solid">Live</Badge>With icons
Badge children can be anything. Drop an inline SVG before the label and the badge's flex layout will space it correctly — gap is already set on the container. Keep icons small (≈ 11 px) and use currentColor so they inherit the badge text colour.
<Badge variant="green">
<CheckIcon />
Verified
</Badge>
<Badge variant="yellow">
<SparkleIcon />
Featured
</Badge>
<Badge variant="red">
<BoltIcon />
Trending
</Badge>Corner radius
The radius prop accepts the shared scale (none / sm / md / lg / pill). Omit it to inherit --bwo-radius-current (defaults to 6 px). pill is the conventional choice for filter / category badges; sm or md reads as more technical / version-tag.
<Badge radius="none">radius=none</Badge>
<Badge radius="sm">radius=sm</Badge>
<Badge radius="md">radius=md</Badge>
<Badge radius="lg">radius=lg</Badge>
<Badge radius="pill">radius=pill</Badge>Recipes
Count badge
Numeric badges sit beside a label to flag pending counts. Use red for urgent / unread, yellow for pending, green for done, and solid for overflow counts (99+).
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
Inbox <Badge variant="red">12</Badge>
</span>
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
Notifications <Badge variant="solid">99+</Badge>
</span>Nav indicator
Pair size="sm" badges with nav items to flag new features, beta sections, or unread counts. Keep the badge subordinate to the nav label — small size, understated colour where possible.
<NavItem label="Inbox" badge={<Badge size="sm" variant="red">12</Badge>} />
<NavItem label="Reports" badge={<Badge size="sm" variant="green">New</Badge>} />
<NavItem label="Billing" badge={<Badge size="sm" variant="soft">Beta</Badge>} />Inline with a heading
Slip a badge into a heading or title to flag a state change. Use display: inline-flex with a small gap so the badge sits on the same baseline as the text.
Pricing changesUpdated
We've restructured the Pro tier — see the new breakdown below.
<CardTitle>
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
Pricing changes
<Badge variant="green" size="sm">Updated</Badge>
</span>
</CardTitle>Version tag
For package version strings, monospace-style tags, and release callouts. Combine a pill-radius soft badge with a dotted "Latest" flag for an at-a-glance state of a release line.
<Badge variant="soft" size="sm" radius="pill">v0.4.0</Badge>
<Badge dot variant="green" size="sm">Latest</Badge>Filter / category tags
Pill-radius soft badges read as quiet category tags or active-filter indicators. For interactive removable chips (filter pills with an × button), badge is display-only — use a regular button styled to match, or open an issue if a closable mode would help.
<Badge variant="soft" radius="pill">Region · EU</Badge>
<Badge variant="soft" radius="pill">Plan · Pro</Badge>
<Badge variant="soft" radius="pill">Created · last 30 d</Badge>Accessibility
- Badge renders a
<span>— it has no implicit semantic role. Screen readers will read the text content inline with whatever surrounds it. That's the right default for label / tag use cases. - For counts (
Inbox 12), the surrounding label already provides context; no extra ARIA is needed. - For status badges that update live (
Online↔Offline), wrap the badge in a region witharia-live="polite"so screen readers announce the change. - Don't rely on colour alone. The
dotprop is a visual aid — the badge text must independently convey the state (Onlineinstead of just a green circle). - If the badge is decorative (e.g. a coloured stamp duplicating information that's already in the surrounding text), add
aria-hidden="true"to avoid double-announcement.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'solid' | 'green' | 'yellow' | 'red' | 'soft' | 'default' | Visual style. See the variant guidance above for when to use each. |
size | 'sm' | 'md' | 'lg' | 'md' | Padding + font-size preset. Small for nav indicators, medium for general use, large for hero callouts. |
dot | boolean | false | Render a small leading dot in the badge’s foreground colour — for status indicators (online / offline / live). |
radius | 'none' | 'sm' | 'md' | 'lg' | 'pill' | — | Corner radius preset. Omit to inherit `--bwo-radius-current` (defaults to 6 px globally). |
…rest | HTMLAttributes<HTMLSpanElement> | — | All native span attributes are forwarded — `onClick`, `aria-label`, `style`, etc. |