---
url: "https://vueda.dev/v3/reference/theming/keys/Badge.md"
title: "Badge"
---

# Badge

Source: `client/lib/theme/vueda-tailwind/display/index.js`

> Compact slab badge with variant and numeric recipes.

Two families of variant share this slot. `default`, `secondary`, and `destructive`
are **solid**: a saturated fill with its own `-foreground` token for the label, and a
transparent hairline so no edge shows. `info`, `success`, and `warning` are **tinted**:
a 10 % surface, the tone itself as the label colour, and a 50 % hairline, which is the
pairing the tone tokens document (see `--success` in `base.css`). Status pills
(for example [ViewHistoryList.typePill](/v3/reference/theming/keys/ViewHistoryList.md#theme-key-ViewHistoryList-typePill)) use this quieter tint;
solid status surfaces such as banner icons pair the tone with its `-foreground`.
Use the solid badge family for identity and counts, the tinted family for status.

Vue component: [Badge](/v3/reference/api/vue/Badge.md)

| Slot | Default classes | Description |
| --- | --- | --- |
| [root](/v3/reference/theming/keys/Badge.md#theme-key-Badge-root) | callback | Compact slab badge with variant and numeric recipes.  Two families of variant share this slot. `default`, `secondary`, and `destructive` are **solid**: a saturated fill with its own `-foreground` token for the label, and a transparent hairline so no edge shows. `info`, `success`, and `warning` are **tinted**: a 10 % surface, the tone itself as the label colour, and a 50 % hairline, which is the pairing the tone tokens document (see `--success` in `base.css`). Status pills (for example [ViewHistoryList.typePill](/v3/reference/theming/keys/ViewHistoryList.md#theme-key-ViewHistoryList-typePill)) use this quieter tint; solid status surfaces such as banner icons pair the tone with its `-foreground`. Use the solid badge family for identity and counts, the tinted family for status. |

<a id="theme-key-Badge-root"></a>

## root

> Compact slab badge with variant and numeric recipes.

Two families of variant share this slot. `default`, `secondary`, and `destructive`
are **solid**: a saturated fill with its own `-foreground` token for the label, and a
transparent hairline so no edge shows. `info`, `success`, and `warning` are **tinted**:
a 10 % surface, the tone itself as the label colour, and a 50 % hairline, which is the
pairing the tone tokens document (see `--success` in `base.css`). Status pills
(for example [ViewHistoryList.typePill](/v3/reference/theming/keys/ViewHistoryList.md#theme-key-ViewHistoryList-typePill)) use this quieter tint;
solid status surfaces such as banner icons pair the tone with its `-foreground`.
Use the solid badge family for identity and counts, the tinted family for status.

Callback:

```javascript
({ variant, numeric }) => ({
            class: [
                // Layout and sizing.
                "inline-flex items-center justify-center",
                "rounded-vueda-control hairline py-0.5",
                "text-xs font-medium",
                "w-fit whitespace-nowrap shrink-0",

                // Icons and child elements.
                "[&>svg]:size-3 gap-1 [&>svg]:pointer-events-none",

                // Focus, invalid, and motion states.
                "focus-visible:focus-ring-shadow",
                "aria-invalid:hairline-destructive aria-invalid:focus-ring-shadow-destructive",
                "transition-colors overflow-hidden",
                {
                    "px-2": !numeric,
                    "font-mono tabular-nums min-w-5 px-1": numeric,
                    // Solid fills hide the edge (transparent hairline colour); `outline` paints a
                    // visible `--border` hairline; the tinted tones paint the tone at 50 %. Each
                    // colour lives in exactly one branch so combineClasses (last-write-wins) never
                    // clears the other, and no two branches set the same custom property with
                    // different values.
                    "[--vueda-hairline-color:transparent]": !TINTED_VARIANTS.has(variant) && variant !== "outline",
                    "hairline-border": variant === "outline",
                    "[--vueda-hairline-color:color-mix(in_oklab,var(--info)_50%,transparent)]": variant === "info",
                    "[--vueda-hairline-color:color-mix(in_oklab,var(--success)_50%,transparent)]":
                        variant === "success",
                    "[--vueda-hairline-color:color-mix(in_oklab,var(--warning)_50%,transparent)]":
                        variant === "warning",
                    "bg-primary text-primary-foreground [a&]:hover:bg-primary-hover [a&]:active:bg-primary-active":
                        !variant || variant === "default",
                    "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary-hover [a&]:active:bg-secondary-active":
                        variant === "secondary",
                    "bg-destructive text-destructive-foreground [a&]:hover:bg-destructive-hover [a&]:active:bg-destructive-active focus-visible:outline-destructive dark:bg-destructive/60":
                        variant === "destructive",
                    "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground [a&]:active:bg-accent-active":
                        variant === "outline",
                    // Tinted semantic tones. Each keeps the tone as its label colour and darkens
                    // the surface a step on an anchor badge's hover and active, so a linked status
                    // pill still reads as pressable without changing family.
                    "text-info bg-info/10 [a&]:hover:bg-info/20 [a&]:active:bg-info/25": variant === "info",
                    "text-success bg-success/10 [a&]:hover:bg-success/20 [a&]:active:bg-success/25":
                        variant === "success",
                    "text-warning bg-warning/10 [a&]:hover:bg-warning/20 [a&]:active:bg-warning/25":
                        variant === "warning",
                },
            ],
        })
```

Source: `client/lib/theme/vueda-tailwind/display/Badge.theme.js:34`
