Badge

Status and metadata badges with icons, presence dots, removable chips, and just enough depth to read as a real surface.

Loading preview

Examples

Practical examples and common states for the same installable component.

Status Stack

Subtle color, shape, and shadow changes for readable state.

examples/badge-status.tsx
import {
IconCheck,
IconClock,
IconShieldCheck,
IconX,
} from "@tabler/icons-react";
import { Badge } from "@/components/wensity/badge";
export function StatusBadges() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="success" leftIcon={<IconCheck />} interactive>
Synced
</Badge>
<Badge variant="warning" leftIcon={<IconClock />} interactive>
Queued
</Badge>
<Badge variant="info" leftIcon={<IconShieldCheck />} interactive>
Protected
</Badge>
<Badge variant="danger" leftIcon={<IconX />} interactive>
Blocked
</Badge>
</div>
);
}

Filter Chips

Removable badges for search, filters, and saved views.

Requires: button

examples/badge-filter-chips.tsx
"use client";
import * as React from "react";
import { IconFilter } from "@tabler/icons-react";
import { Badge } from "@/components/wensity/badge";
import { Button } from "@/components/wensity/button";
export function FilterChips() {
const [chips, setChips] = React.useState(["Free", "React", "Animated"]);
return (
<div className="flex flex-wrap gap-2">
<Badge variant="outline" leftIcon={<IconFilter />}>
Components
</Badge>
{chips.map((chip) => (
<Badge
key={chip}
variant={chip === "Animated" ? "brand" : "neutral"}
onRemove={() =>
setChips((current) => current.filter((item) => item !== chip))
}
removeLabel={`Remove ${chip}`}
>
{chip}
</Badge>
))}
{chips.length === 0 ? (
<Button
size="sm"
variant="secondary"
onClick={() => setChips(["Free", "React", "Animated"])}
>
Reset filters
</Button>
) : null}
</div>
);
}

Plan Labels

Small commercial labels with enough polish for pricing and account UI.

examples/badge-plan.tsx
import { IconLock, IconStar } from "@tabler/icons-react";
import { Badge } from "@/components/wensity/badge";
export function PlanBadges() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="neutral" size="sm">
Starter
</Badge>
<Badge variant="brand" size="sm" leftIcon={<IconStar />}>
Pro
</Badge>
<Badge variant="carbon" size="sm" leftIcon={<IconLock />}>
Team
</Badge>
</div>
);
}

Live States

Dot badges for uptime, queues, streaming, and async work.

examples/badge-live.tsx
import { Badge } from "@/components/wensity/badge";
export function LiveBadges() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="success" dot pulseDot>
Online
</Badge>
<Badge variant="warning" dot>
Delayed
</Badge>
<Badge variant="danger" dot>
Paused
</Badge>
</div>
);
}

Icon Badges

Icon slots preserve rhythm without turning badges into buttons.

examples/badge-icons.tsx
import {
IconArrowUpRight,
IconBolt,
IconDatabase,
IconPlayerPlay,
IconSparkles,
} from "@tabler/icons-react";
import { Badge } from "@/components/wensity/badge";
export function IconBadges() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="brand" leftIcon={<IconSparkles />} interactive>
Fresh
</Badge>
<Badge variant="info" leftIcon={<IconDatabase />} interactive>
Synced
</Badge>
<Badge variant="warning" leftIcon={<IconBolt />} interactive>
Usage high
</Badge>
<Badge
variant="carbon"
leftIcon={<IconPlayerPlay />}
rightIcon={<IconArrowUpRight />}
interactive
>
Launch
</Badge>
</div>
);
}

Sizes

Three sizes that keep text, icons, and dots aligned.

examples/badge-sizes.tsx
import { IconFlame, IconShieldCheck } from "@tabler/icons-react";
import { Badge } from "@/components/wensity/badge";
export function BadgeSizes() {
return (
<div className="flex flex-wrap items-center gap-2">
<Badge size="sm" variant="success" dot>
Small
</Badge>
<Badge size="md" variant="brand" leftIcon={<IconFlame />}>
Default
</Badge>
<Badge size="lg" variant="carbon" leftIcon={<IconShieldCheck />}>
Large
</Badge>
</div>
);
}

Shapes

Different radius options for compact, app, and pill contexts.

examples/badge-shapes.tsx
import { Badge } from "@/components/wensity/badge";
export function BadgeShapes() {
return (
<div className="flex flex-wrap items-center gap-2">
<Badge radius="sm" variant="outline">
Square
</Badge>
<Badge radius="md" variant="info">
Rounded
</Badge>
<Badge radius="pill" variant="success" dot>
Pill
</Badge>
</div>
);
}

Props

PropTypeDefaultDescription
variant"neutral" | "success" | "warning" | "danger" | "info" | "brand" | "carbon" | "outline""neutral"Status colour recipe, drawn from the shared status tokens.
size"sm" | "md" | "lg""md"Height, padding, and text size.
radius"sm" | "md" | "pill""pill"Corner rounding. pill is fully round.
interactivebooleanfalseAdds hover and focus affordances for badges that act as filters or buttons.
dotbooleanfalseRenders a leading status dot in the variant colour.
pulseDotbooleanfalseAnimates the status dot to signal a live or ongoing state.
leftIconReact.ReactNode-Icon before the label.
rightIconReact.ReactNode-Icon after the label.
onRemove() => void-When set, renders a remove button. Use for token or filter chips.
removeLabelstring"Remove"Accessible label for the remove button.
asChildbooleanfalseRenders the child element instead of a span, keeping styles.