Badge
A small label for status, category or count. Two published components, fifteen variants each, five colours across three states.
Thirty variants, no size axis
Badge and Badge Number are published separately but share both axes and every colour. The label version hugs its text; the number version is a fixed 20px circle, because a counter that changes width as the count grows is a counter that makes the row jump.
| Variant | Default | Hover | Focus |
|---|---|---|---|
| Default | Badge8 | Badge8 | Badge8 |
| Secondary | Badge8 | Badge8 | Badge8 |
| Outline | Badge8 | Badge8 | Badge8 |
| Destructive | Badge8 | Badge8 | Badge8 |
| Ghost | Badge8 | Badge8 | Badge8 |
A ring around it, never a repaint
Focus adds a 2px outer ring at half opacity and changes nothing else. Compare Default and Default/Focus above: the fill is the same base.primary in both. Recolouring on focus would make the badge look like a different variant, which is exactly what a focus ring is meant to avoid.
Destructive is the one exception, and only in the ring's colour: neutral would read as an error next to the red fill, so the ring picks up base.destructive at 20%.
Outline already has a 1px border, so on focus the file switches that border to an inner stroke and puts the 2px ring outside it. Two strokes on one shape have to sit on different alignments or Penpot draws them on top of each other.
On Outline and Ghost, hover also drops the label to base.muted-foreground. The other three variants keep their text colour and move only the fill. It is drawn that way in the file rather than being a rounding error.
Two components, thirty variants
Read straight out of the Penpot file. The axes below are the property names you will see in the variant dropdown.
Using the Badge
Because a badge is often a link or a filter chip rather than plain text - a tag you can click to filter by it, a status you can click to open. shadcn/ui lets the badge render as an anchor, so the kit draws the states that come with that. Used as a static label, you simply never leave Default.
Nothing here can be disabled. A badge that is not interactive has no disabled meaning, and one that is interactive is a link - links do not disable, they disappear or stop being links. Adding the variant would have been three more drawings of the same thing.
When the content is a count. It is a fixed 20px circle rather than a pill that hugs its text, so a row of counters stays aligned as the numbers change. Past two digits it stops being a circle, and at that point the honest answer is a pill with a plus.
Outline carries a border and no fill; Ghost carries neither until you hover it. Ghost is for badges sitting inside something that already has edges - a table cell, a list row - where another border would be one line too many.