Skip to main content

Badge

Implemented

Numeric count badge for notification and nav counts. Count-based API (number or max+), never children. Five semantic variants on ADR-027 tint/fg pairs — WCAG 2.2 AA (≥4.5:1) in light and dark themes.

Categoryatoms
Sourcesrc/components/atoms/Badge/Badge.tsx
AI HintCount-driven pill for notification and nav counts. Pass a number (count) — never children. Counts above max render as `${max}+`. Pair with ariaLabel (defaults to `${count} item(s)`). Composable via IconButton/Sidebar/Tabs badge slots — prefer slots over hand-rolled positioned spans.

Numeric count badge for notification counts and nav item counts. Count-based API with a max cap and five semantic variants.

Badge

Count/Display atom (Tier 1)

A small numeric pill that communicates a count (notifications, nav items, cart lines). Renders a formatted number or `${max}+` — never free-form children.

599+2731

This component supports light and dark mode.

Usage

The badge is count-based: it renders a number (or max+), not children. Always pass a descriptive ariaLabel when the bare number is ambiguous — the root is role="status" and announces the label. The variants use semantic colors tuned for WCAG 2.2 AA contrast on both light and dark surfaces.

import { Badge } from '@epasslive/design-system'

<Badge count={3} ariaLabel="3 new events" />
<Badge count={140} max={99} variant="error" ariaLabel="140 unread notifications" />
<Badge count={2} variant="info" ariaLabel="2 draft events" />

// Pair with a nav item for count display
<NavLink href="/dashboard">
  Dashboard <Badge count={7} ariaLabel="7 pending orders" />
</NavLink>

When to use

  • Counts, not words — notification counts, nav-item counts, cart lines, filter results. For semantic states carried by a label (Confirmed, Pending, Refunded), use StatusBadge instead.
  • Prefer badge slots — IconButton (badge.count + showDot), Sidebar (badge.count + badge.ariaLabel) and Tabs (badge number) already position, cap and announce counts. Never hand-roll an absolutely-positioned count span.
  • Count-based API — pass count (never children); counts above max render as max+.
  • Localized apps — pass ariaLabel from the translation catalog; the fallback accessible name is English N item(s).

Dark mode

Four variants use ADR-027 semantic tint/fg pairs; neutral uses bg-3 + text-heading. All meet WCAG 2.2 AA in both light and dark themes.

Props

Prop
Type
Default
Description
count*
number
—

Numeric count to display. Must be a non-negative integer.

max
number
99

Cap the displayed value; counts above render as `${max}+`.

variant
'error' | 'success' | 'warning' | 'neutral' | 'info'
'error'

Visual variant — color encodes semantic intent.

ariaLabel
string
—

Descriptive aria-label (e.g. ‘3 new events’). Falls back to `${count} item(s)`.

Props

Preview

Badge

Prop
Type
Required
Default
Description
count
number
Required
—

Numeric count to display. Non-integer inputs are floored; negative values clamp to 0.

max
number
Optional
99

Cap the displayed value; counts above render as `${max}+`.

variant
'error' | 'success' | 'warning' | 'neutral' | 'info'
Optional
'error'

Visual variant. error/success/warning/info use ADR-027 tint/fg pairs (WCAG AA in both themes); neutral uses bg-3/text-heading.

ariaLabel
string
Optional
—

Descriptive aria-label (e.g. '3 new events'). Falls back to `${count} item(s)`.

Quick use:<Badge />

Accessibility

ARIA rolestatus

Type

1 rule

NASA Rule 5

count must be a non-negative integer

ARIA

1 rule

WCAG 1.3.1

Visible count must be paired with descriptive aria-label (e.g. count=3, label='3 new events')

Usage

Import

tsxSnippet
import { Badge } from "@epasslive/design-system"

Example 1

tsxSnippet
<Badge count={5} />

Example 2

tsxSnippet
<Badge count={99} max={99} variant="error" />

Example 3

tsxSnippet
<Badge count={3} variant="error" ariaLabel="3 new events" />

Anti-patterns

— Do not compose atoms directly — use molecules instead

— Avoid inline styles on atoms

— Never pass children — the API is count-based (count or `${max}+`)

Design System v4.1.0 | ePassLive