Badge
Compact label for status, category, or count. Four variants cover most use cases.
Examples
Variants
Five styles for status, category, and emphasis.
import { Badge } from "@codefast/ui/badge";
export function BadgeVariants() {
return (
<div className="flex flex-wrap gap-2">
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="ghost">Ghost</Badge>
</div>
);
}
Custom Colors
You can customize the colors of a badge by adding custom classes such as bg-green-50 dark:bg-green-800 to the Badge component.
import { Badge } from "@codefast/ui/badge";
export function BadgeCustomColors() {
return (
<div className="flex flex-wrap gap-2">
<Badge className="bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300">Blue</Badge>
<Badge className="bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300">Green</Badge>
<Badge className="bg-sky-50 text-sky-700 dark:bg-sky-950 dark:text-sky-300">Sky</Badge>
<Badge className="bg-purple-50 text-purple-700 dark:bg-purple-950 dark:text-purple-300">Purple</Badge>
<Badge className="bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-300">Red</Badge>
</div>
);
}
With Icon
You can render an icon inside the badge. Use data-icon='inline-start' to render the icon on the left and data-icon='inline-end' to render the icon on the right.
import { Badge } from "@codefast/ui/badge";
import { BadgeCheck, BookmarkIcon } from "lucide-react";
export function BadgeWithIconLeft() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="secondary">
<BadgeCheck data-icon="inline-start" />
Verified
</Badge>
<Badge variant="outline">
Bookmark
<BookmarkIcon data-icon="inline-end" />
</Badge>
</div>
);
}
RTL
Right-to-left layout support for languages such as Arabic and Hebrew.
Translations are AI-generated for demonstration and may be imperfect.
import { Badge } from "@codefast/ui/badge";
import { BadgeCheck, BookmarkIcon } from "lucide-react";
import type { Translations } from "#/features/components-catalog/components/detail/language";
import { useTranslation } from "#/features/components-catalog/components/detail/language-context";
const translations: Translations = {
en: {
dir: "ltr",
values: {
badge: "Badge",
secondary: "Secondary",
destructive: "Destructive",
outline: "Outline",
verified: "Verified",
bookmark: "Bookmark",
},
},
ar: {
dir: "rtl",
values: {
badge: "شارة",
secondary: "ثانوي",
destructive: "مدمر",
outline: "مخطط",
verified: "متحقق",
bookmark: "إشارة مرجعية",
},
},
he: {
dir: "rtl",
values: {
badge: "תג",
secondary: "משני",
destructive: "הרסני",
outline: "קווי מתאר",
verified: "מאומת",
bookmark: "סימנייה",
},
},
};
export function BadgeRtl() {
const { dir, t } = useTranslation(translations, "ar");
return (
<div className="flex w-full flex-wrap justify-center gap-2" dir={dir}>
<Badge>{t.badge}</Badge>
<Badge variant="secondary">{t.secondary}</Badge>
<Badge variant="destructive">{t.destructive}</Badge>
<Badge variant="outline">{t.outline}</Badge>
<Badge variant="secondary">
<BadgeCheck data-icon="inline-start" />
{t.verified}
</Badge>
<Badge variant="outline">
{t.bookmark}
<BookmarkIcon data-icon="inline-end" />
</Badge>
</div>
);
}
With Spinner
You can render a spinner inside the badge. Remember to add the data-icon='inline-start' or data-icon='inline-end' prop to the spinner.
import { Badge } from "@codefast/ui/badge";
import { Spinner } from "@codefast/ui/spinner";
export function BadgeWithSpinner() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="destructive">
<Spinner data-icon="inline-start" />
Deleting
</Badge>
<Badge variant="secondary">
Generating
<Spinner data-icon="inline-end" />
</Badge>
</div>
);
}
Link
Use the asChild prop to render a link as a badge.
import { Badge } from "@codefast/ui/badge";
import { ArrowUpRightIcon } from "lucide-react";
export function BadgeAsLink() {
return (
<Badge asChild>
<a href="#link">
Open Link <ArrowUpRightIcon data-icon="inline-end" />
</a>
</Badge>
);
}
Usage
The minimal import and composition — see Examples below for styled, real-world variants.
import { Badge } from "@codefast/ui/badge";
export function BadgeUsage() {
return <Badge>Badge</Badge>;
}
Anatomy
How the parts nest — every slot the component exposes, in composition order.
Features
- Six variants — default, secondary, outline, destructive, ghost, link.
- asChild renders the child element (e.g. a link) instead of a <span>.
- A child marked data-icon="inline-start" or "inline-end" (an icon or a Spinner) gets matching spacing automatically, same convention as Button.
API reference
Props for each part of the component. All native element props are also forwarded.
Badge
Renders a <span>, or its child element when asChild is set.
variant"default" | "secondary" | "outline" | "destructive" | "ghost" | "link"Visual style of the badge.
Default
"default"asChildbooleanMerge props onto the single child — e.g. an <a> — instead of a <span>.
Default
false
Accessibility
Built to be keyboard-navigable and screen-reader friendly out of the box.
- A badge is decorative text by default and needs no role.
- When a badge conveys status (e.g. “Error”), keep the meaning in the text, not colour alone.
- When made interactive via asChild, ensure the child element is itself focusable (a link or button).
Guidelines
Conventions that keep usage consistent across an app.
Do
- Keep badge text to one or two words.
- Use destructive/secondary variants to map to a consistent status scale.
Don’t
- Don’t put long sentences or interactive controls inside a badge.
- Don’t use a badge as the only signal for critical state.
Explore further
Ready to integrate?
Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.