Compact label for statuses, counts, and metadata.
Description
Badge is a small, non-interactive label used to tag content with a status, count, or category. It is a single-element component rendered as a <span> by default, with optional leading and trailing icons.
Reach for it when you need to surface a piece of metadata next to other content, such as an item state next to a row, a count on a navigation item, a tag in a list, or a category on a card. The visual weight is intentionally low so it complements the content it sits beside instead of competing with it.
Don't use Badge when the user needs to interact with it. If it triggers an action, use Button. If it represents an inline call-to-attention with title and body copy, use Alert. If it's a colored dot indicating presence (online / offline / away), use Status Badge. Reserve Badge for passive labels.
Installation
Usage
Examples
Variants
variant sets the semantic color. Twelve options cover product intents (primary), neutral metadata, status tones (success, danger, warning, info), and specialty tones (verified, highlighted, away, inverse).
Appearance
appearance controls fill weight. soft is the default and works well in dense lists. solid is high-contrast for emphasis, outline is quiet, and ghost strips the background entirely.
Sizes
Three sizes (xs, sm, md) match the surrounding type scale. sm is the default.
Shape
shape="pill" makes the badge fully rounded; rounded (default) follows the size's radius scale.
With Icon
Use leadingIcon and trailingIcon to render an icon inline. The component handles spacing and sizing per the active size.
Icon Only
iconOnly removes horizontal padding and forces a square footprint. Always pair with an aria-label so screen readers can announce the meaning.
Number Only
numberOnly is the count style: square-ish, centered, and designed for notification numerals (1, 12, 99) on navigation items or avatars.
Accessibility
Badge is a passive label. By default it renders as a <span> and is not focusable; there are no keyboard interactions to document. If you render it as a link or button via the asChild prop, focus and keyboard behavior come from that underlying element.
ARIA notes:
- The component sets no implicit role; treat purely-decorative badges as such (e.g. add
aria-hidden="true"). - For badges that carry meaning beyond their visible label (e.g. an unread count), make sure the surrounding context exposes that meaning, either through the badge's text content or with
aria-labelon the parent control. - When using
iconOnly, always provide anaria-labelbecause the visual icon alone is not announced.
Styling
Tailwind override: pass className to merge Tailwind classes with the component's CVA classes (via cn()):
Data slots and attributes: the component sets these for CSS targeting:
data-slot="badge"on the root element.data-slot="badge-icon"on each icon wrapper (leading and trailing).data-slot="badge-label"on the inner text wrapper.data-variant="<variant>",data-appearance="<appearance>",data-size="<size>"on the root.
Target a specific state in CSS:
Related Components
- Status Badge: colored dot + label for presence states (online, offline, away).
- App Store Badge: branded download CTA for App Store / Play Store.
- Button: use this when the element needs to be interactive.
- Alert: use this for full callouts with title and description, not inline labels.
API Reference
Badge
Passive label for tagging content with a status, count, or category. Extends React.ComponentProps<"span">, so any standard span attribute (id, role, aria-*, onClick, etc.) is accepted.