Badge
Displays a badge or a component that looks like a badge.
When to Use
Use Badge when you need to:
- Label or categorize content with short descriptive tags
- Display status indicators (active, pending, complete, error)
- Show notification counters for unread items or alerts
- Highlight metadata such as version numbers, roles, or permissions
- Create clickable tag links for filtering or navigation (using asChild)
Default
The default appearance of the badge component with all variants, icons, and counters.
Variants
The four built-in visual styles for different emphasis levels and semantic meaning.
With Icons
Badges with leading icons for status indication. Icons are automatically sized to 12px via the component styles.
Counters
Circular notification counter badges using rounded-full, monospace tabular numbers, and compact sizing.
As Link
Use asChild to render badges as clickable anchor elements while preserving badge styling and hover states.
UX & Design Guidelines
Visual Hierarchy
Use variant="default" for primary emphasis (active states, highlights), variant="secondary" for neutral tags and categories, variant="outline" for subtle labels, and variant="destructive" for errors, warnings, and critical counts. Avoid mixing too many badge variants in a single row.
Spacing & Layout
When grouping badges, use gap-2 for tight layouts (inline tags) or gap-4 for standard spacing. Badges are inline-flex and shrink-0 by default, so they will not wrap text or collapse in flex containers. Use flex-wrap on the parent to allow wrapping.
Responsive Behavior
Badges have a fixed text-xs size and compact padding, making them suitable for all screen sizes. On mobile, ensure badge groups use flex-wrap to prevent horizontal overflow. Counter badges use min-w-5 for consistent circular sizing even with single digits.
Color & Contrast
All badge variants meet WCAG 2.1 AA contrast requirements. The default variant uses bg-primary with text-primary-foreground for maximum contrast. When using custom colors via className, verify contrast ratios manually. The outline variant relies on text-foreground on a transparent background for a subtle appearance.
Accessibility
Keyboard Navigation
- Static badges (span elements) are not focusable by default, which is correct for decorative labels
- When using
asChildwith links, Tab moves focus to the badge link - Enter activates link badges (standard anchor behavior)
- Focus ring uses
focus-visible:ring-[3px]for clear visibility
Screen Reader Support
- Badges render as
<span>elements and are read inline with surrounding text - Icon-only badges require
aria-labelfor screen reader users - For counter badges that update dynamically, add
role="status"andaria-live="polite" - Link badges announce their text content and role automatically via the anchor element
Focus Management
Visible focus ring with 3px width using focus-visible:ring-[3px]. Focus states use focus-visible:border-ring and focus-visible:ring-ring/50 for consistent ring styling. Destructive badges use a red ring via focus-visible:ring-destructive/20.
Color Independence
Do not rely solely on color to convey meaning. Pair badge colors with descriptive text or icons (e.g., a check icon with "Complete" rather than a green badge alone). This ensures users with color vision deficiencies can interpret badge meaning.
ARIA Attributes
{/* Standard badge */}
<Badge>Active</Badge>
{/* Icon-only badge - requires aria-label */}
<Badge aria-label="3 notifications">
<BellIcon className="size-3" />
</Badge>
{/* Status badge with role for dynamic updates */}
<Badge role="status" aria-live="polite">
{unreadCount} new messages
</Badge>
{/* Badge used as a link */}
<Badge asChild>
<a href="/notifications" aria-label="View all notifications">
Notifications
</a>
</Badge>Related Components
API Reference
The Badge component accepts the following props in addition to standard span attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "secondary" | "destructive" | "outline" | "default" | The visual style variant of the badge. |
| asChild | boolean | false | When true, the badge renders its child as the root element, merging props and behavior. |
| className | string | — | Additional CSS classes to apply to the badge. |
| children | ReactNode | — | The badge content (text, icons, counters, etc.). |