- Accordion
- Agent Thinking
- Alert
- Alert Dialog
- Announcement
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Checkbox Card
- Code Block
- Collapsible
- Color Picker
- Combobox
- Command
- Composer
- Composer Loader
- Context Menu
- Data Grid
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- File Upload
- Hover Card
- Input
- Input Group
- Input Otp
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Meter
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Period Switcher
- Popover
- Progress
- Questionnaire
- Radio Card
- Radio Group
- Resizable
- Reveal
- Scroll Area
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Social Button
- Sonner
- Spinner
- Status Dot
- Switch
- Switch Card
- Table
- Tabs
- Tag Group
- Textarea
- Theme Toggle
- Time Field
- Toggle
- Toggle Group
- Tooltip
- Trace
- Tree View
- Agent Creator 01
- Agent Limits Card 01
- Agent Progress 01
- AI Chat 01
- AI Image Generation 01
- AI Profile 01
- Alerts Card 01
- Auth Card 01
- Calendar 01
- Composer 01
- Composer Attachments 01
- Composer Panel 01
- Finance Dashboard 01
- Home Dashboard 01
- Marketing Dashboard 01
- Medical Profile 01
- Meeting Scheduler 01
- Multi Agent Chat 01
- Notification Center 01
- Patient Info Card 01
- Project Board 01
- Questionnaire 01
- Settings Modal 01
- Sidebar 01
- Stat Cards 01
- Task List 01
- Web Search 01
- Activity Rings Card 01
- Area Chart Card 01
- Bar List Card 01
- Combo Chart Card 01
- Contributions Card 01
- Earnings Chart Card 01
- Funnel Chart Card 01
- Heatmap Chart Card 01
- Line Chart Card 01
- Most Active Days Card 01
- Orders Chart Card 01
- Radar Chart Card 01
- Radial Chart Card 01
- Revenue Chart Card 01
- Sankey Chart Card 01
- Scatter Chart Card 01
- Sleep Score Card 01
- Stage Bars Card 01
- Steps Card 01
DefaultSecondaryDestructiveOutlineGhostLink
124ReadyIn progressEditor
OrangeRoseYellowCyanNeutralGraySoft
+1,204312Nov 8
Installation
$ pnpm dlx shadcn@latest add @cobalt/badge
Options
variant="label"is the 14px label chip;subtleis the same with 4px more height;captionis the 12px version.shape="pill"makes any variant fully rounded.tabularuses equal-width digits, for counts and amounts that change.size="xs"is a tighter 6px badge (px-1.5 py-px) for thecounter,label,subtleandcaptionvariants.
Source
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva } from "class-variance-authority";
import type { VariantProps } from "class-variance-authority";
import { cn } from "cn";
const badgeVariants = cva(
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
{
defaultVariants: {
variant: "default",
},
variants: {
variant: {
counter:
"h-auto gap-0 rounded-[4px] border-0 px-1 py-px text-xs leading-4 font-semibold tracking-normal transition-none",
label:
"h-auto gap-0 rounded-[6px] border-0 px-1.5 py-0.5 text-sm leading-5 font-medium tracking-normal transition-[padding,font-size] duration-200 ease-[ease] motion-reduce:transition-none",
subtle:
"h-auto gap-0 rounded-[6px] border-0 px-1.5 py-1 text-sm leading-5 font-medium tracking-normal transition-[padding,font-size] duration-200 ease-[ease] motion-reduce:transition-none",
caption:
"h-auto gap-0 rounded-[6px] border-0 px-1.5 py-1 text-xs leading-4 font-medium tracking-[0.15px] transition-[padding,font-size] duration-200 ease-[ease] motion-reduce:transition-none",
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
destructive:
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
ghost:
"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
link: "text-primary underline-offset-4 hover:underline",
outline:
"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
secondary:
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
},
},
}
);
const badgeTones = {
primary:
"bg-[var(--badge-primary-background,var(--primary))] text-[color:var(--badge-primary-foreground,var(--primary-foreground))]",
destructive:
"bg-[var(--badge-destructive-background,var(--destructive))] text-[color:var(--badge-destructive-foreground,var(--destructive-foreground,var(--primary-foreground)))]",
neutral:
"bg-[var(--badge-neutral-background,var(--surface-strong,var(--muted)))] text-[color:var(--foreground-secondary,var(--muted-foreground))]",
gray: "bg-[var(--surface-subtle,var(--muted))] text-foreground",
soft: "bg-[var(--surface-subtle,var(--muted))] text-[color:var(--foreground-secondary,var(--muted-foreground))]",
orange:
"bg-[var(--badge-orange-background,var(--muted))] text-[color:var(--badge-orange-foreground,var(--foreground))]",
lime: "bg-[var(--badge-lime-background,var(--muted))] text-[color:var(--badge-lime-foreground,var(--foreground))]",
rose: "bg-[var(--badge-rose-background,var(--muted))] text-[color:var(--badge-rose-foreground,var(--foreground))]",
yellow:
"bg-[var(--badge-yellow-background,var(--muted))] text-[color:var(--badge-yellow-foreground,var(--foreground))]",
cyan: "bg-[var(--badge-cyan-background,var(--muted))] text-[color:var(--badge-cyan-foreground,var(--foreground))]",
blue: "bg-[var(--badge-blue-background,var(--muted))] text-[color:var(--badge-blue-foreground,var(--foreground))]",
purple:
"bg-[var(--badge-purple-background,var(--muted))] text-[color:var(--badge-purple-foreground,var(--foreground))]",
} as const;
function Badge({
className,
variant = "default",
render,
tone,
shape = "default",
size = "default",
tabular = false,
...props
}: useRender.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & {
tone?: keyof typeof badgeTones;
/**
* `pill` makes any variant fully rounded. `circle` is a 20px round count
* (e.g. on a bell) that grows into a pill for longer numbers.
*/
shape?: "default" | "pill" | "circle";
/** `xs` is a tighter 6px badge for the counter, label, subtle and caption variants. */
size?: "default" | "xs";
/** Equal-width digits, for counts and amounts that change. */
tabular?: boolean;
}) {
const quiet = ["counter", "label", "subtle", "caption"].includes(
variant ?? ""
);
return useRender({
defaultTagName: "span",
props: mergeProps<"span">(
{
className: cn(
badgeVariants({ variant }),
quiet && badgeTones[tone ?? "neutral"],
quiet && size === "xs" && "rounded-[6px] px-1.5 py-px",
shape === "pill" && "rounded-full",
shape === "circle" &&
"h-5 min-w-5 justify-center rounded-full px-1 py-0 leading-5 tabular-nums",
tabular && "tabular-nums",
className
),
},
props
),
render,
state: {
slot: "badge",
variant,
},
});
}
export { Badge, badgeVariants }; On this page