A small, non-interactive label that attaches a fact — duration, category, status, count — to something else.
When to Use
Use when:
You're annotating a card, row, or heading with metadata the reader scans rather than reads — "45 min", "Ideation", "Completed", "3". Badges are static by design.
Don't use when:
The label does something when clicked — use Button. For an activity type use Activity Badge, for a removable tag use Pill, and for anything longer than three words use plain text.
Variants
Types
Six variants. category takes a custom color; status takes a status key; the rest are self-contained.
The only state. Badges are static <span>s — no hover, focus, active, or disabled treatment.
Inside an interactive parent
A badge in a hoverable card inherits nothing; the parent owns the hover. The --transition-fast token is present for parent-driven colour changes.
Empty text
Renders an empty badge — a visible coloured sliver. Guard against empty strings at the call site.
Real-World Usage
A library card's meta row: category from the database with its stored colour, duration via the shorthand, and a status badge only when the item needs attention.
default | duration | category | status | count | new
size
string
'md'
sm | md | lg
icon
string
null
Material icon rendered before the text. Not auto-selected — even duration needs it passed explicitly (the ws_duration() shorthand does this for you).
color
string
null
Hex colour for the category variant, applied inline
status
string
null
success | warning | error | info. Only meaningful with variant: 'status'.
pill
bool
false
Full border-radius
id
string
null
Element ID
class
string
''
Additional CSS classes
attrs
array
[]
Extra HTML attributes as key/value pairs
Accessibility
Concern
Behavior
ARIA
None applied. The badge is a text <span> in the document flow, so its content is announced in reading order along with whatever it annotates.
Keyboard
Not focusable. If a badge ever needs to be actionable, that's a Button.
Colour independence
The label always carries the meaning in words — "Completed", not a bare green dot. Preserve that: don't ship a status badge whose text is generic while only the colour distinguishes it.
Context for counts
The count variant renders a bare number, which is meaningless alone to a screen-reader user. Put the noun in adjacent text or an aria-label on the parent — "3 unread notes", not "3".
Contrast
Built-in variants pair tested token foreground/background. A custom color on the category variant bypasses that — check it before shipping.