Badge

Label a status or a category.

Verified

Usage

import { Badge } from "@voila.dev/ui/badge";
<Badge variant="destructive">Failed</Badge>

Badge covers two jobs that look the same and are not: labelling status (pending, failed, verified) and labelling category (a tag, a skill, a department). The first is semantic and uses variant; the second is arbitrary and uses color.

Recipes

Status, where the colour means something

DefaultSecondaryOutlineDestructiveGhostLink

default is neutral emphasis, secondary quieter metadata, outline the quietest of all, destructive something failed or expired, ghost and link the interactive chips.

Category chips coloured from data

slategrayzincredorangeamberyellowlimegreenemeraldtealcyanskyblueindigovioletpurplefuchsiapinkrose

Twenty fixed names, each with a --badge-* token and a dark override so chips stay legible in both themes. Use them when the colour is a property of the thing being labelled and it came out of a database:

<Badge color={skill.color}>{skill.name}</Badge>

The set is deliberately closed: storing "emerald" in your data and mapping it to a token means a chip renders the same everywhere. color wins over variant if you pass both. The names are exported as badgeColors with the BadgeColor type.

A badge that navigates

Solid variants only hover when rendered as an anchor, so the chips that are clickable are distinguishable. For a chip the user can remove, reach for Chip instead; it has the dismiss affordance built in.

API

PropTypeDefault
color"amber" | "blue" | "cyan" | "emerald" | "fuchsia" | "gray" | "green" | "indigo" | "lime" | "orange" | "pink" | "purple" | "red" | "rose" | "sky" | "slate" | "teal" | "violet" | "yellow" | "zinc"Catalogue palette, for category rather than status. Overrides variant when both are set.
size"default" | "sm""default"sm for dense surfaces such as table cells. Below that, use text.
variant"brand" | "default" | "destructive" | "ghost" | "highlight" | "link" | "outline" | "secondary""default"Semantic intent, for status: pending, failed, verified. For an arbitrary category — a tag, a skill, a department — use color.
renderComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

Plus every <span> prop. Source: badge/components/badge.tsx.

Colour alone is not an accessible status indicator; the label inside the badge is doing the work and the colour is reinforcement. Never ship a badge whose only content is a colour.

Every state is in the Storybook story.

Own it

The source is @voila.dev/ui/src/badge/components/badge.tsx. To change the palette or the variants, edit the cva block and the --badge-* tokens next to it. It is the same file whether you keep the package or copy it into your repo.

Chip · Button · StatCard