ComponentsBadge
Badge
Show a short status, label, or count.
On this page
Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.
View registry filesImport the component into your page or component file.
Usage
import { Badge } from "@dethink/components";
export function Example() {
return <Badge tone="success">Healthy</Badge>;
}Try the examples, then open the code to use them in your app.
Variants and tones
Combine emphasis and semantic tone without hard-coding product colors.
solid
NeutralFeaturedHealthyReviewFailedAI assisted
soft
NeutralFeaturedHealthyReviewFailedAI assisted
outline
NeutralFeaturedHealthyReviewFailedAI assisted
subtle
NeutralFeaturedHealthyReviewFailedAI assisted
Show sourceexamples/badge/variants.tsx
examples/badge/variants.tsx
"use client";
import {
AlertTriangle,
CheckCircle2,
CircleDot,
Info,
Sparkles,
XCircle,
} from "lucide-react";
import { Badge, type BadgeTone, type BadgeVariant } from "@dethink/components";
const variants: BadgeVariant[] = ["solid", "soft", "outline", "subtle"];
const tones: Array<{
icon: typeof CircleDot;
label: string;
tone: BadgeTone;
}> = [
{ icon: CircleDot, label: "Neutral", tone: "neutral" },
{ icon: Sparkles, label: "Featured", tone: "primary" },
{ icon: CheckCircle2, label: "Healthy", tone: "success" },
{ icon: AlertTriangle, label: "Review", tone: "warning" },
{ icon: XCircle, label: "Failed", tone: "destructive" },
{ icon: Info, label: "AI assisted", tone: "info" },
];
export function BadgeVariants() {
return (
<div className="grid w-full gap-5">
{variants.map((variant) => (
<div key={variant} className="grid gap-2">
<p className="text-muted-foreground text-sm font-medium capitalize">
{variant}
</p>
<div className="flex flex-wrap items-center gap-[var(--dt-space-2)]">
{tones.map(({ icon: Icon, label, tone }) => (
<Badge key={tone} icon={<Icon />} tone={tone} variant={variant}>
{label}
</Badge>
))}
</div>
</div>
))}
</div>
);
}Sizes
Choose xs for dense tables, sm and md for routine metadata, and lg for higher emphasis.
XSxs
SMsm
MDmd
LGlg
Show sourceexamples/badge/sizes.tsx
examples/badge/sizes.tsx
"use client";
import { Badge, type BadgeSize } from "@dethink/components";
const sizes: BadgeSize[] = ["xs", "sm", "md", "lg"];
export function BadgeSizes() {
return (
<div className="flex flex-wrap items-center gap-[var(--dt-space-3)]">
{sizes.map((size) => (
<div key={size} className="grid justify-items-center gap-2">
<Badge size={size} tone="primary" variant="soft">
{size.toUpperCase()}
</Badge>
<span className="text-muted-foreground text-xs">{size}</span>
</div>
))}
</div>
);
}Icons
Icons are decorative, so the text label carries the accessible meaning.
Sync completeReview pendingAI draft ready
Show sourceexamples/badge/icons.tsx
examples/badge/icons.tsx
"use client";
import { ArrowRight, CheckCircle2, Clock3, Sparkles } from "lucide-react";
import { Badge } from "@dethink/components";
export function BadgeIcons() {
return (
<div className="flex flex-wrap items-center gap-[var(--dt-space-3)]">
<Badge icon={<CheckCircle2 />} tone="success">
Sync complete
</Badge>
<Badge icon={<Clock3 />} iconPlacement="trailing" tone="warning">
Review pending
</Badge>
<Badge
leadingIcon={<Sparkles />}
trailingIcon={<ArrowRight />}
tone="info"
variant="outline"
>
AI draft ready
</Badge>
</div>
);
}Status list recipe
Badges keep repeated operational states compact and easy to scan.
Show sourceexamples/badge/recipe-status-list.tsx
examples/badge/recipe-status-list.tsx
"use client";
import { AlertTriangle, CheckCircle2, Clock3, XCircle } from "lucide-react";
import {
Badge,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@dethink/components";
const services = [
{
icon: CheckCircle2,
label: "Healthy",
name: "Billing worker",
tone: "success" as const,
variant: "soft" as const,
},
{
icon: Clock3,
label: "Queued",
name: "Registry smoke",
tone: "info" as const,
variant: "outline" as const,
},
{
icon: AlertTriangle,
label: "Needs review",
name: "Import pipeline",
tone: "warning" as const,
variant: "outline" as const,
},
{
icon: XCircle,
label: "Failed",
name: "Email sender",
tone: "destructive" as const,
variant: "solid" as const,
},
];
export function BadgeStatusList() {
return (
<Card className="w-full max-w-lg">
<CardHeader>
<CardTitle>Service health</CardTitle>
<CardDescription>
Compact badges keep operational state scannable in repeated rows.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-3">
{services.map(({ icon: Icon, label, name, tone, variant }) => (
<div
key={name}
className="flex min-w-0 items-center justify-between gap-[var(--dt-space-4)]"
>
<span className="truncate text-sm font-medium">{name}</span>
<Badge icon={<Icon />} size="xs" tone={tone} variant={variant}>
{label}
</Badge>
</div>
))}
</CardContent>
</Card>
);
}BadgeProps extends span attributes for routine metadata and status labels.
| Prop | What it does | Default |
|---|---|---|
variant"solid" | "soft" | "outline" | "subtle" | Visual weight of the badge. | "soft" |
tone"neutral" | "primary" | "success" | "warning" | "destructive" | "info" | Semantic color tone resolved through design tokens. | "neutral" |
size"xs" | "sm" | "md" | "lg" | Badge height, padding, gap, and text size. | "md" |
iconReactNode | Decorative icon placed according to iconPlacement unless explicit leading or trailing icons are set. | Not set |
iconPlacement"leading" | "trailing" | Position for the icon prop. | "leading" |
leadingIconReactNode | Decorative icon rendered before the badge label. | Not set |
trailingIconReactNode | Decorative icon rendered after the badge label. | Not set |
childrenReactNode | Visible badge label. Keep it short enough for dense rows. | Not set |