Badge
A small label for status, category, or metadata.
labelstatus
Preview
Badge preview
Live · keyboard ready
NeutralShippedBetaDeprecatedBlockedSmall
When to use
- Short statuses next to titles or in table cells, such as Live, Draft, or Failed.
- Counts or states that change in place and should morph instead of jump.
- Tagging a row with one tone plus an optional icon.
When not to use
- Use alert or toast when the message needs a full sentence.
- Use chip-group when people toggle the values.
- Use stat-card for a headline number with a trend.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "badge",
"type": "registry:ui",
"title": "Badge",
"description": "A small label for status, category, or metadata.",
"categories": [
"data"
],
"dependencies": [
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/badge/badge.tsx",
"type": "registry:component",
"target": "@components/manicat/badge/badge.tsx"
},
{
"path": "registry/components/badge/badge.module.css",
"type": "registry:component",
"target": "@components/manicat/badge/badge.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/badge",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/badge",
"markdown": "https://uiarc.dev/components/badge/markdown",
"tags": [
"label",
"status"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { Badge } from "@/components/manicat/badge/badge";
export function BadgeExample() {
return (
<div className="flex flex-wrap items-center gap-2">
<Badge>Neutral</Badge>
<Badge tone="success">Shipped</Badge>
<Badge tone="info">Beta</Badge>
<Badge tone="warning">Deprecated</Badge>
<Badge tone="danger">Blocked</Badge>
<Badge tone="neutral" size="sm">Small</Badge>
</div>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Status column Tones carry meaning: green is done, amber needs attention, red is broken.
Status column
Tones carry meaning: green is done, amber needs attention, red is broken. preview
Live · keyboard ready
- marketing-siteLive
- billing-apiDegraded
- docs-previewBuilding
- legacy-adminFailed
- playgroundPaused
status-column-tones-carry-meaning-green-is-done-amber-needs-attention-red-is-broken-.tsxtsx
"use client";
import { Badge } from "@/components/manicat/badge/badge";
export function BadgeStatusExample() {
const rows = [
{ name: "marketing-site", tone: "success", label: "Live" },
{ name: "billing-api", tone: "warning", label: "Degraded" },
{ name: "docs-preview", tone: "info", label: "Building" },
{ name: "legacy-admin", tone: "danger", label: "Failed" },
{ name: "playground", tone: "neutral", label: "Paused" },
] as const;
return (
<ul className="grid w-full max-w-sm divide-y divide-(--border) rounded-[var(--radius-panel)] border border-(color:--border) bg-(--surface)">
{rows.map((row) => (
<li key={row.name} className="flex items-center justify-between px-4 py-3">
<span className="font-mono text-sm text-(color:--foreground)">{row.name}</span>
<Badge tone={row.tone}>{row.label}</Badge>
</li>
))}
</ul>
);
}
Accessibility
- Renders a plain span, so it is read inline with surrounding text.
- The icon is aria-hidden; the label must state the status on its own, not rely on tone color.
- Outgoing labels are hidden from assistive tech while they fade, so only the current text is read.
- It does not announce changes. Put it inside a live region if a status update must be spoken.
Motion
- A new label rises in with a short blur while the old one lifts away, and the pill width springs to fit.
- Passive reflows such as font swaps resize instantly; only a content change springs.
- Reduced motion swaps the label with a quick fade and snaps the width.
Responsive behavior
- The pill sizes to its label and never wraps, so keep labels to a word or two in narrow cells.
- Hover styles apply only on hover-capable fine pointers.
Performance
- Each badge has a ResizeObserver for the width spring; fine per row, but avoid thousands in one table.
- Font swaps and passive reflows resize instantly; only content changes animate.
Notes for AI
- Use for short statuses and counts next to titles or in table cells. Use alert or toast for messages with sentences.
- Keep the badge mounted and change its children to get the morph; remounting with a new key loses it.