All components

Status Badge

Composable status primitive with semantic tones, variants, live/deploy pulses, meta text, and removable/selectable tag behaviour.

Default
Live status, loading spinners, meta text, and interactive removable tags.
Live system status
Online/offline with pulsing dot indicators.
API healthyWorker offlineLive
Loading / deploy
Spinner for loading; deploy with optional pulse dot.
Deploying v2.4.1SyncingRolling update
With meta
Primary label plus secondary metric or timestamp.
Database12msCache stale2m agoGateway503
Interactive tags
Selectable filters with removable chips.
ProductionEU-WestPaid plan

Click to select · dismiss to remove

1"use client";
2
3import { useState } from "react";
4
5import {
6 Card,
7 CardContent,
8 CardDescription,
9 CardHeader,
10 CardTitle,
11} from "@/components/ui/card";
12import { StatusBadge, StatusBadgeList } from "@/registry/ui";
13
14export function StatusBadgeExamples() {
15 const [tags, setTags] = useState(["Production", "EU-West", "Paid plan"]);
16 const [active, setActive] = useState("Production");
17
18 return (
19 <div className="grid gap-6 md:grid-cols-2">
20 <Card>
21 <CardHeader>
22 <CardTitle className="text-base">Live system status</CardTitle>
23 <CardDescription>
24 Online/offline with pulsing dot indicators.
25 </CardDescription>
26 </CardHeader>
27 <CardContent>
28 <div className="flex flex-wrap items-center gap-2">
29 <StatusBadge status="online" dot pulse>
30 API healthy
31 </StatusBadge>
32 <StatusBadge status="offline" dot variant="outline">
33 Worker offline
34 </StatusBadge>
35 <StatusBadge status="online" dot pulse size="sm" variant="solid">
36 Live
37 </StatusBadge>
38 </div>
39 </CardContent>
40 </Card>
41
42 <Card>
43 <CardHeader>
44 <CardTitle className="text-base">Loading / deploy</CardTitle>
45 <CardDescription>
46 Spinner for loading; deploy with optional pulse dot.
47 </CardDescription>
48 </CardHeader>
49 <CardContent>
50 <div className="flex flex-wrap items-center gap-2">
51 <StatusBadge status="deploying" loading>
52 Deploying v2.4.1
53 </StatusBadge>
54 <StatusBadge status="info" loading variant="outline">
55 Syncing
56 </StatusBadge>
57 <StatusBadge status="deploying" dot pulse>
58 Rolling update
59 </StatusBadge>
60 </div>
61 </CardContent>
62 </Card>
63
64 <Card>
65 <CardHeader>
66 <CardTitle className="text-base">With meta</CardTitle>
67 <CardDescription>
68 Primary label plus secondary metric or timestamp.
69 </CardDescription>
70 </CardHeader>
71 <CardContent>
72 <div className="flex flex-col items-start gap-3">
73 <StatusBadge status="success" meta="12ms">
74 Database
75 </StatusBadge>
76 <StatusBadge status="warning" meta="2m ago" variant="outline">
77 Cache stale
78 </StatusBadge>
79 <StatusBadge status="error" meta="503" size="sm">
80 Gateway
81 </StatusBadge>
82 </div>
83 </CardContent>
84 </Card>
85
86 <Card>
87 <CardHeader>
88 <CardTitle className="text-base">Interactive tags</CardTitle>
89 <CardDescription>
90 Selectable filters with removable chips.
91 </CardDescription>
92 </CardHeader>
93 <CardContent>
94 <div className="flex flex-col gap-3">
95 <StatusBadgeList>
96 {tags.map((tag) => (
97 <StatusBadge
98 key={tag}
99 status={active === tag ? "info" : "neutral"}
100 selectable
101 selected={active === tag}
102 removable
103 variant={active === tag ? "solid" : "soft"}
104 onClick={() => setActive(tag)}
105 onRemove={() => {
106 setTags((current) => {
107 const next = current.filter((t) => t !== tag);
108 setActive((prev) => (prev === tag ? next[0] ?? "" : prev));
109 return next;
110 });
111 }}
112 >
113 {tag}
114 </StatusBadge>
115 ))}
116 </StatusBadgeList>
117 <p className="text-xs text-muted-foreground">
118 Click to select · dismiss to remove
119 </p>
120 </div>
121 </CardContent>
122 </Card>
123 </div>
124 );
125}

Installation & source

Install via the shadcn CLI or copy the registry files manually.

bash
npx shadcn@latest add @tt-ui/status-badge

Props

NameTypeDefaultDescription
status"neutral" | "success" | "warning" | "error" | "info" | "online" | "offline" | "deploying""neutral"Semantic tone; online/deploying enable pulse defaults
variant"solid" | "soft" | "outline""soft"Visual weight; soft uses subtle gradients
size"sm" | "md""md"Compact or default density
iconReactNodemapped default per statusOverrides default icon; ignored when loading
dotbooleanauto for online/deployingLeading status dot; pulse animates the dot only
pulse / loadingbooleanfalsePulse on dot; loading shows spinner instead of icon
metastringundefinedSecondary text (latency, timestamp, code)
removable / onRemoveboolean / () => voidundefinedDismiss button when both are set
selectable / selectedbooleanfalseSelection ring; use with onClick