Badge
Compact status tag with signal, semantic-tier, and data variants.
"use client";import { Badge } from "@/registry/okibi/ui/badge";export default function BadgeDemo() { return ( <div className="flex flex-wrap items-center justify-center gap-2"> <Badge variant="signal">Signal</Badge> <Badge variant="outline">Outline</Badge> <Badge variant="success">Secure</Badge> <Badge variant="warning">Trace</Badge> <Badge variant="destructive">Breach</Badge> <Badge variant="data">SEC-04</Badge> </div> );}npx shadcn@latest add https://okibi.cndr.dev/r/badge.jsonInstallation
Install the theme first, then add the component:
npx shadcn@latest add https://okibi.cndr.dev/r/badge.jsonInstall the required dependencies:
npm install @radix-ui/react-slot class-variance-authorityCopy the source from the Code tab above into components/ui/badge.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.
Usage
import { Badge } from "@/components/ui/badge"
<Badge variant="signal">Online</Badge>Examples
Tiers
The semantic color tiers — magenta, cyan, success, warning, info, and special — each a solid token fill for status taxonomies.
import { Badge } from "@/registry/okibi/ui/badge";export default function BadgeTiersDemo() { return ( <div className="flex flex-wrap items-center justify-center gap-2"> <Badge variant="magenta">PRIORITY</Badge> <Badge variant="cyan">UPLINK</Badge> <Badge variant="success">SECURE</Badge> <Badge variant="warning">TRACE</Badge> <Badge variant="info">NOTICE</Badge> <Badge variant="special">CLASSIFIED</Badge> </div> );}Outline
outline drops the fill for a hairline keyline tag; pair it with the solid default/data variants to rank emphasis.
import { Badge } from "@/registry/okibi/ui/badge";export default function BadgeOutlineDemo() { return ( <div className="flex flex-wrap items-center justify-center gap-2"> <Badge variant="default">SIGNAL</Badge> <Badge variant="outline">OUTLINE</Badge> <Badge variant="data">SEC-04</Badge> </div> );}With icon
Drop a Lucide icon in as the first child — it auto-sizes to the label and is spaced by the built-in gap.
import { Radio, Shield } from "lucide-react";import { Badge } from "@/registry/okibi/ui/badge";export default function BadgeWithIconDemo() { return ( <div className="flex flex-wrap items-center justify-center gap-2"> <Badge variant="signal"> <Radio /> UPLINK </Badge> <Badge variant="success"> <Shield /> SECURE </Badge> </div> );}As link
asChild applies the badge styling to its child, so a badge can be a real, navigable a while keeping the tag look.
import { Badge } from "@/registry/okibi/ui/badge";export default function BadgeAsChildDemo() { return ( <Badge asChild variant="data"> <a href="#">SEC-04 ↗</a> </Badge> );}API Reference
Badge
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "signal" | "outline" | "magenta" | "cyan" | "success" | "warning" | "info" | "special" | "destructive" | "data" | "default" | Fill / tier style. |
asChild | boolean | false | Render the styles on the child (e.g. an <a>). |
Accessibility
- Renders a non-interactive
spanby default — it is decorative text, not a status region. - Color alone is not an accessible signal; for live status pair a visually-hidden label or
role='status'with the tier color. - Tier fills use paired
*-foregroundtokens, so the label text clears contrast on every variant. - A focus-visible 2px signal ring is wired in, so
asChildlinks and buttons stay keyboard-visible. - With
asChild, pass interactive semantics on the child (anawithhref, or abutton) — the badge only lends styling.
Guidelines
Do
- Map tier color to meaning consistently —
success,warning,destructive,infofor state;datafor mono readouts. - Back color with a word or icon so the status survives grayscale and color-blindness.
- Use
asChildto wrap anawhen a badge needs to navigate, e.g. a filter chip. - Keep labels to a token or two — chips are single-line by design.
Don't
- Don't lean on color alone to convey status — add text or an
aria-label. - Don't use a badge as a button without
asChildand real interactive markup. - Don't feed long strings into a badge; they won't wrap or truncate gracefully.
- Don't mix tiers arbitrarily in one cluster — reserve
destructivefor actual failures.