Light

Badge

Displays a badge or a component that looks like a badge.

Spec · from metadata

When to use

  • Displaying status labels (active, pending, error, success)
  • Tagging or categorizing content
  • Counts or short metadata indicators
  • Color-coded labels in tables, lists, or cards

When not to use

  • Interactive chip that can be dismissed — use a custom chip component
  • Navigation tabs — use Tabs component
  • Buttons — use Button even if it looks small

Variants

PropValuesDefaultDescription
variantdefaultsecondarydestructiveoutlineghostlinkdefaultNeutraldefaultNavydefaultBerrydefaultSagedefaultOrangeoutlineNeutraloutlineNavyoutlineBerryoutlineSageoutlineOrangedefaultSemantic variants (default, secondary, destructive, outline, ghost, link) for standard use. Primitive variants (default*/outline* + color) for brand-specific color needs.

Anti-patterns

Avoid<Badge className="bg-green-500 text-white">Success</Badge>
Prefer<Badge variant="defaultSage">Success</Badge>

Never use arbitrary Tailwind colors. Use a semantic or primitive color variant.

Avoid<Badge variant="default" onClick={handleClick}>Click me</Badge>
Prefer<Button size="xs" variant="secondary">Click me</Button>

Badge is not interactive. For clickable elements, use Button.

Accessibility

  • Screen readerBadge is a <span> with no implicit role. For status indicators, consider adding role='status' or an aria-label for context.
  • ContrastAll variants are designed to meet WCAG AA contrast. Destructive uses white text on destructive background.

Token bindings

TokenCategoryUsage
bg-primarycolorDefault variant background
bg-secondarycolorSecondary variant background
bg-destructivecolorDestructive variant background
border-bordercolorOutline variant border
tc-berry-600, tc-sage-600, tc-orange-300, tc-navy-*, tc-gray-*colorPrimitive color variant tokens (tc-berry replaces deprecated tc-magenta as of 2026 brand refresh)
rounded-fullradiusPill shape border radius

Import

import { Badge } from "@timelycare/helix-ui"

Props

interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
  variant?:
    | "default"
    | "secondary"
    | "outline"
    | "destructive"
    | "ghost"
    | "link"
    | "defaultNeutral"
    | "defaultNavy"
    | "defaultBerry"
    | "defaultSage"
    | "defaultOrange"
    | "outlineNeutral"
    | "outlineNavy"
    | "outlineBerry"
    | "outlineSage"
    | "outlineOrange"
  asChild?: boolean
  className?: string
  children: React.ReactNode
}

Variants

VariantUse ForBackgroundText Color
defaultPrimary actions, main categoriesbg-primarytext-primary-foreground
secondaryNeutral status, less prominent labelsbg-secondarytext-secondary-foreground
outlineSubtle indicators, bordered tagsbg-transparenttext-foreground
destructiveErrors, critical statusbg-destructivetext-destructive-foreground
ghostMinimal styling, no backgroundtransparentinherits
linkLinked badges with underline on hovertransparenttext-primary
defaultNeutralNeutral/category (filled)tc-gray-900white
defaultNavyPrimary blue (filled)primary (tc-navy-700)primary-foreground
defaultBerryBerry accent (filled)tc-berry-600white
defaultSageGreen/success (filled)tc-sage-600white
defaultOrangeOrange/warning (filled)tc-orange-300black
outlineNeutralNeutral outlinetc-gray-100tc-gray-900 (border: tc-gray-200)
outlineNavyNavy outlinetc-navy-50primary (border: tc-navy-200)
outlineBerryBerry outlinetc-berry-50tc-berry-600 (border: tc-berry-200)
outlineSageSage outlinetc-sage-50tc-sage-600 (border: tc-sage-200)
outlineOrangeOrange outlinetc-orange-50tc-orange-900 (border: tc-orange-200)

Choosing a Variant

  • Default: Main categories, active status, primary labels
  • Secondary: Tags, neutral metadata, less important info
  • Outline: Minimal styling, subtle indicators, bordered tags
  • Destructive: Errors, removal actions, critical status
  • Ghost: Ultra-minimal, no background or border
  • Link: Navigational badges with underline on hover
  • defaultNeutral / defaultNavy / defaultBerry / defaultSage / defaultOrange: Filled badges using primitive color tokens; use for status, categories, or emphasis by color.
  • outlineNeutral / outlineNavy / outlineBerry / outlineSage / outlineOrange: Outline badges with a solid light background (50-step), colored border (200-step), and matching text; use for subtle tags or secondary emphasis.

Styling

Typography

PropertyValue
Fontfont-sans (Adelle Sans)
Sizetext-xs (12px)
Weightfont-semibold
Line Heightleading-4 (16px)

Dimensions

PropertyValue
Height20px
Paddingpx-2 py-0.5 (8px horizontal, 2px vertical)
Border Radiusrounded-full (pill / full rounded shape)
Icon Gapgap-1 (4px)

All badges use the full rounded (pill) shape. Do not use rounded-sm or other radii for badge components.

Color variants (primitive tokens)

Filled (default) and outline variants use Helix primitive color scales. Anatomy:

Default (filled) — 5 color variants

VariantBackground tokenText token
defaultNeutraltc-gray-900white
defaultNavyprimary (tc-navy-700)primary-foreground
defaultBerrytc-berry-600white
defaultSagetc-sage-600white
defaultOrangetc-orange-300black

Outline — 5 color variants (solid light background, 1px border, matching text)

VariantBackgroundBorderText
outlineNeutraltc-gray-100tc-gray-200tc-gray-900
outlineNavytc-navy-50tc-navy-200primary
outlineBerrytc-berry-50tc-berry-200tc-berry-600
outlineSagetc-sage-50tc-sage-200tc-sage-600
outlineOrangetc-orange-50tc-orange-200tc-orange-900

Icons

Size: size-3 (12×12px) — automatic via [&>svg]:size-3 Spacing: gap-1 (4px) — built into badge flex layout

IconUse For
CheckCompleted, approved
AlertCircleAlerts, attention needed
ArrowRightLinks, navigation
XRemovable badges
StarFeatured items

States

StateImplementation
DefaultBase appearance
HoverBuilt-in opacity/color change (anchor badges only via [a&]:hover:)
Focusring-[3px] ring-ring/50 border-ring

Common Patterns

Basic Variants

<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="destructive">Destructive</Badge>

With Icons

import { Check, ArrowRight } from "lucide-react"

<Badge>
  <Check />
  Approved
</Badge>

<Badge>
  Link
  <ArrowRight />
</Badge>

Notification Count (Badge Number)

// Single digit - circular
<Badge className="size-5 rounded-full p-0 justify-center">8</Badge>

// Double digit
<Badge className="h-5 min-w-5 rounded-full px-1.5 justify-center">99</Badge>

// Overflow
<Badge className="rounded-full px-2">20+</Badge>

Pending/Processing

<Badge variant="outline" className="gap-1">
  <LoaderCircle className="size-3 animate-spin" />
  Processing
</Badge>

In Context

// With card title
<div className="flex items-center gap-2">
  <CardTitle>Article Title</CardTitle>
  <Badge variant="secondary">New</Badge>
</div>

// User status
<div className="flex items-center gap-2">
  <Avatar />
  <span>Username</span>
  <Badge className="gap-1">
    <BadgeCheck />
    Verified
  </Badge>
</div>

Component Structure

{/* Standard Badge */}
<span className="inline-flex items-center justify-center gap-1 rounded-full bg-primary px-2 py-0.5 text-xs font-semibold text-primary-foreground">
  {/* Optional left icon */}
  <Check className="size-3" />
  
  {/* Badge text */}
  Badge
  
  {/* Optional right icon */}
  <ArrowRight className="size-3" />
</span>

{/* Badge Number (circular) */}
<span className="inline-flex size-5 items-center justify-center rounded-full bg-primary p-0 text-xs font-semibold text-primary-foreground">
  8
</span>

Accessibility

  • Styled inline element — no interactive behavior
  • Screen reader: reads badge text content automatically
  • Use aria-label if badge meaning isn't clear from text alone
  • No keyboard interaction (non-interactive element)
  • Use asChild to render as a different element (e.g., anchor for linked badges)

Gotchas

ProblemSolution
Badge too tallDefault height is 20px; use py-0.5 padding
Icon wrong sizeSVGs auto-size to size-3 (12px) via [&>svg]:size-3
Notification badge not circularAdd rounded-full and size-5 for single digit
Need removable badgeAdd X icon with click handler
Icons not alignedUse gap-1 for proper spacing
Need a navigational badgeUse variant="link" with asChild wrapping an anchor

See Also

  • Related Components: Avatar (avatar with status badge), Button (actionable badges)
  • Tokens: Colors — Theme-aware color tokens

Last updated: April 22, 2026