Status Badge
Semantic wrapper over Badge that maps admin status names to visual variants with a colored indicator dot and optional pulse animation — copy it into your project and own it completely.
Basic
All Statuses (Subtle)
Admin-UI Event Tones
A second vocabulary covers admin-ui event lifecycle states — useful for events
tables, ticket listings, and any content that moves through a publish /
schedule / live / sold-out / archived flow. Each tone maps to an existing
semantic color group, so no new tokens are introduced. scheduled reads as
info (blue) — an upcoming/committed state — deliberately distinct from
draft's muted neutral grey, so a committed-but-not-yet-live item never looks
like an unpublished one.
CRM / Pipeline Stages
A third vocabulary covers CRM and sales-pipeline stages — useful for deal
boards, client lists, and any record that moves through a prospect → pitched →
contracted → active → completed flow (plus paused and archived). Each stage
maps to an existing semantic color group, so no new tokens are introduced.
Stages that share a meaning share a color: contracted, active, and
completed all read as in-good-standing success.
All Statuses (Filled)
Pulsing Indicator
Use pulse on in-flight states like running or pending to draw the eye.
The animation is skipped automatically when the user has
prefers-reduced-motion enabled.
Custom Label
Without Indicator
Installation
npx visor add status-badgeThis copies the component into your project and pulls badge as a
transitive registry dependency:
components/ui/status-badge/status-badge.tsx— the componentcomponents/ui/status-badge/status-badge.module.css— the stylescomponents/ui/badge/badge.tsx— the underlying Badge (auto-installed)components/ui/badge/badge.module.css— Badge styles (auto-installed)
Usage
import { StatusBadge } from '@/components/ui/status-badge/status-badge';
export default function Example() {
return <StatusBadge status="healthy" />;
}API Reference
StatusBadgeProps
| Prop | Type | Default | Description |
|---|---|---|---|
status* | 'healthy' | 'degraded' | 'down' | 'failed' | 'running' | 'pending' | 'queued' | 'idle' | 'complete' | 'live' | 'warn' | 'scheduled' | 'sold' | 'draft' | 'prospect' | 'pitched' | 'contracted' | 'active' | 'paused' | 'completed' | 'archived' | — | Semantic admin status. Drives the underlying Badge variant, the indicator dot color, and the default label. |
label | React.ReactNode | — | Visible text. Defaults to the capitalized status key (e.g. "Healthy", "Running"). |
tone | 'subtle' | 'filled' | 'subtle' | Which Badge variant family to use. Filled uses saturated backgrounds; subtle uses tinted surfaces. |
indicator | boolean | true | Render the leading colored indicator dot. |
pulse | boolean | false | Animate the indicator dot with a soft pulse. Respects prefers-reduced-motion. |
className | string | — | Additional CSS class names to merge onto the root element. |
...props | Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> | — | All standard HTML attributes (except children) are forwarded to the underlying Badge element. |
Status → Variant Mapping
| Status | Color group | Subtle variant | Filled variant |
|---|---|---|---|
healthy | success | success | filled-success |
complete | success | success | filled-success |
degraded | warning | warning | filled-warning |
pending | warning | warning | filled-warning |
down | destructive | destructive | filled-destructive |
failed | destructive | destructive | filled-destructive |
running | info | info | filled-info |
queued | neutral | neutral | filled-neutral |
idle | neutral | neutral | filled-neutral |
live | success | success | filled-success |
warn | warning | warning | filled-warning |
scheduled | info | info | filled-info |
sold | success | success | filled-success |
draft | neutral | neutral | filled-neutral |
prospect | info | info | filled-info |
pitched | warning | warning | filled-warning |
contracted | success | success | filled-success |
active | success | success | filled-success |
paused | warning | warning | filled-warning |
completed | success | success | filled-success |
archived | neutral | neutral | filled-neutral |
Neutral statuses use Badge's neutral variant in subtle tone (a --surface-muted
background) and the filled-neutral variant in filled tone (a solid
--color-neutral-600 fill with white text and dot) — both legible in light and
dark mode.
Accessibility
Color alone is never sufficient to communicate a status. StatusBadge always
renders a visually-hidden Status: prefix before the label so screen
readers announce the full phrase — e.g. "Status: Healthy" — regardless
of which tone or indicator state is active. The indicator dot is marked
aria-hidden so assistive tech ignores the decorative glyph.
The pulse animation is wrapped in a prefers-reduced-motion guard and is
paused entirely for users who have requested reduced motion.
Source Files
After running npx visor add status-badge, you'll have:
status-badge.tsx
A forwardRef component that composes <Badge> unchanged and layers on the
semantic status → variant mapping, the indicator dot, and the accessible
prefix.
status-badge.module.css
Only the additions on top of Badge: the indicator dot (sized and colored via CSS custom properties), the pulse keyframes, and the visually-hidden utility. Everything else — padding, radius, typography, background — is inherited from Badge.
Customization
After copying the component, you own it completely. Common customizations:
- Add a new status (e.g.
maintenance) by extending the color group map. - Localize
statusBadgeLabelsby importing and overriding specific keys. - Swap the indicator dot for a Phosphor icon per status (e.g.
CheckCircle,WarningCircle). - Tune the pulse timing by editing the
@keyframesblock in the CSS module.
Stat Hero
Hero-scale animated metric banner for flagship KPI display. A 35/65 grid banner with a large headline value on the left and a full-height animated trendline on the right — copy it into your project and own it completely.
Accordion
Vertically stacked collapsible sections. Built on Radix UI with single or multiple expansion modes.