Badge
A compact inline label for status, category or metadata, with an optional icon, avatar and close button.
Installation
bash
npx @smicolon/cli init
npx @smicolon/cli add badgePreview
NewPaidFeatured
Variants
variant sets the visual weight and tone the meaning. Solid is the loudest; Soft lays a tint over the card surface, so it reads the same wherever it sits; Outline is the quietest.
NewDraftIn reviewPaidAwaiting paymentOverdue
NewDraftIn reviewPaidAwaiting paymentOverdue
NewDraftIn reviewPaidAwaiting paymentOverdue
radius="standard" swaps the pill for the design system’s small radius.
NewNewNewNew
Sizes
Heights are minimums: 20, 22 and 26px in English. Arabic’s taller line grows them to 24, 24 and 28px rather than squeezing the text.
FeaturedFeaturedFeatured
States
Pass onClose and the badge gets a real close button. Tab to one to see the focus ring, which wraps the whole badge 2px out.
DesignEngineeringResearchMarketing
FeaturedLaylaLaylaReviewer
Accessibility
- The badge is a plain
<span>. Only the close button is interactive, and it is a native<button>. - The close button is named after the label, "Remove Cairo", or "إزالة القاهرة" when the nearest
langis Arabic. It follows a language change without a reload. PasscloseLabelfor more context, such as "Remove filter: Cairo". - The icon is decorative and hidden from assistive technology. The avatar is not: give the Avatar a
name, orname=""when the label already names the person. - Don’t rely on tone alone to carry meaning — the label should say it.
- Direction is inherited from
dir, never a prop, so the badge can never disagree with the page.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The label. |
variant | "solid" | "soft" | "outline" | "solid" | Visual weight. |
tone | "primary" | "secondary" | "info" | "success" | "warning" | "destructive" | "primary" | Meaning, shown as colour. |
size | "sm" | "md" | "lg" | "sm" | Badge size. |
radius | "rounded" | "standard" | "rounded" | Pill or small radius. |
icon | ReactNode | — | Icon before the label. |
avatar | ReactNode | — | Avatar before the label. |
onClose | (event) => void | — | Adds a close button; called when pressed. |
closeLabel | string | — | Close button’s accessible name, in the page language by default. |
className | string | — | Extra classes for the component. |
Usage
tsx
import { Badge } from "@/components/ui/badge"
import { Avatar } from "@/components/ui/avatar"
<Badge>New</Badge>
<Badge variant="soft" tone="success">Paid</Badge>
<Badge variant="outline" tone="destructive" size="md">Overdue</Badge>
// Icon and avatar — the badge sizes and colours them
<Badge icon={<Star />}>Featured</Badge>
<Badge avatar={<Avatar size="12" radius="rounded" src={user.photo} name="" />}>
{user.name}
</Badge>
// Removable
<Badge variant="soft" onClose={() => remove(tag)} closeLabel={`Remove filter: ${tag}`}>
{tag}
</Badge>