Badge
A short label in the line of text: a status, a count, a category. Five variants in seven colours.
- Kbd draws its key symbols at the size of the capPassingfix/kbd-symbols-at-cap-sizebugkbd
- Charts in a new entry, cennge-ui/chartsRunningfeat/chartsfeaturecharts
- Carousel dots show the pointer cursorFailingfix/carousel-dot-cursorbugcarousel
- Labels are flat, the default; the branch is faded, the count solid, the checks a dot.
- The dot is hidden from screen readers, so the word beside it says the status.
- The branch badge has a max width: a longer name ends in an ellipsis instead of widening the row.
Field marks
- Import
import { Badge } from "cennge-ui";- Size
- 1.1 KB gzip for this import, its dependencies aside
- Pattern
- A
<span>: no role, not focusable - SSR
- Rendered on the server in the Next.js check; hydrates without a warning
- Defaults
- Colour and size from
CenngeProviderwhen you set them there - Tests
- Unit tests
- Source
- src/components/badge
When to use#
Use a Badge for a word or a number that labels something next to it: the state of a CI run, an issue's labels, the count on a tab. It is text, not a control. If clicking it should do something, use a Button with size="sm".
Similar#
- Indicator pins a dot or a count to the corner of another element, such as an icon button or an avatar; a Badge sits in the line.
- TagsInput makes tags you add and remove; a Badge only shows one.
Variants and colours#
flat is the default. solid is the loudest, for the one badge that must be seen; dot keeps the text neutral and puts the colour in a dot before it. primary takes the accent, the other colours keep their meaning.
import { Badge, type BadgeVariant, type CenngeColor } from "cennge-ui";
const variants: BadgeVariant[] = ["solid", "flat", "bordered", "faded", "dot"];
const colors: CenngeColor[] = ["default", "primary", "secondary", "success", "warning", "danger", "info"];
export default function BadgeVariants() {
return (
<div className="grid grid-cols-[4.5rem_1fr] items-start gap-x-4 gap-y-3">
{variants.map((variant) => (
<div key={variant} className="contents">
<span className="text-sm leading-6 text-muted">{variant}</span>
<div className="flex flex-wrap gap-1.5">
{colors.map((color) => (
<Badge key={color} variant={variant} color={color}>
{color}
</Badge>
))}
</div>
</div>
))}
</div>
);
}Counts and icons#
A count after a tab's name is a small Badge inside the trigger. startContent and endContent put an icon before or after the text; mark the icon aria-hidden, the text already says it.
import { Badge, Tabs, TabsContent, TabsList, TabsTrigger } from "cennge-ui";
function CheckIcon() {
return (
<svg viewBox="0 0 24 24" className="size-3.5" fill="none" stroke="currentColor" strokeWidth="2.75" aria-hidden="true">
<path d="M5 12.5l4.5 4.5L19 7.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
export default function RepositoryTabs() {
return (
<Tabs defaultValue="code" className="w-full max-w-md">
<TabsList aria-label="payload-cache">
<TabsTrigger value="code">Code</TabsTrigger>
<TabsTrigger value="issues">
Issues
<Badge size="sm">4</Badge>
</TabsTrigger>
<TabsTrigger value="pulls">
Pull requests
<Badge size="sm">1</Badge>
</TabsTrigger>
</TabsList>
<TabsContent value="code" className="flex items-center gap-2 pt-3 text-sm">
payload-cache@1.4.0
<Badge color="success" size="sm" startContent={<CheckIcon />}>
Latest
</Badge>
</TabsContent>
<TabsContent value="issues" className="pt-3 text-sm text-muted">
Four open issues.
</TabsContent>
<TabsContent value="pulls" className="pt-3 text-sm text-muted">
One open pull request.
</TabsContent>
</Tabs>
);
}Sizes, radius and long text#
Three sizes, and radius from none to full, the default. The text sits in its own truncating span, so a narrow parent cuts it with an ellipsis instead of pushing the layout wider.
import { Badge } from "cennge-ui";
export default function BadgeSizes() {
return (
<div className="flex flex-col gap-4">
<div className="flex flex-wrap items-center gap-2">
<Badge size="sm" color="primary">
Small
</Badge>
<Badge size="md" color="primary">
Medium
</Badge>
<Badge size="lg" color="primary">
Large
</Badge>
</div>
<div className="flex flex-wrap items-center gap-2">
<Badge variant="bordered" radius="sm">
v0.3.1
</Badge>
<Badge variant="bordered" radius="md">
MIT
</Badge>
<Badge variant="bordered" radius="full">
TypeScript
</Badge>
</div>
{/* A badge never grows past its parent: long text ends in an ellipsis. */}
<div className="w-40">
<Badge variant="faded">fix/select-chevron-inside-an-open-dialog</Badge>
</div>
</div>
);
}Accessibility#
A Badge is a plain <span> that screen readers read with the text around it: a tab named "Issues 4". Its colour is not announced and the dot of variant="dot" is aria-hidden, so the words must carry the meaning: "Failing", not a red badge alone.
Props#
Also takes every attribute of <span>, except color, which mean something else here.