Skip to content
Dethink Components

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 files

Import 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.

Service health

Compact badges keep operational state scannable in repeated rows.

Billing workerHealthy
Registry smokeQueued
Import pipelineNeeds review
Email senderFailed
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.

Badge props
PropWhat it doesDefault
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"
iconReactNodeDecorative icon placed according to iconPlacement unless explicit leading or trailing icons are set.Not set
iconPlacement"leading" | "trailing"Position for the icon prop."leading"
leadingIconReactNodeDecorative icon rendered before the badge label.Not set
trailingIconReactNodeDecorative icon rendered after the badge label.Not set
childrenReactNodeVisible badge label. Keep it short enough for dense rows.Not set