Badge
A short label that tags a record with an attribute, a category or a count.
@zenoxai/ui/components/badge Markdown<>
<Badge variant="soft" tone="neutral">
Production
</Badge>
<Badge variant="soft" tone="primary">
Internet-facing
</Badge>
<Badge variant="outline">Linux</Badge>
</>Usage
import { Badge } from "@zenoxai/ui/components/badge"
export function ExposureTag() {
return (
<Badge variant="soft" tone="primary">
Internet-facing
</Badge>
)
}
Use a badge for attributes of a record that the user scans for: an environment, an asset type, a tag, a count. Keep the label to one or two words, in sentence case.
Use something else when the badge would show:
- The state of a record (new, in progress, resolved, failed). Use StatusBadge. It takes a semantic tone and a label, and keeps the status-to-tone mapping in one place in the app.
- A severity level (critical, high, medium, low). Use SeverityBadge, which uses the severity scale colors.
Variant and tone
The Zenox variants, soft, solid and outline, take a tone that sets the color. Without a
tone they are neutral.
function BadgeMatrix() {
const variants = ["soft", "solid", "outline"] as const
const tones = [
"neutral",
"primary",
"success",
"warning",
"danger",
"info",
] as const
return (
<div className="grid gap-3">
{variants.map((variant) => (
<div key={variant} className="flex flex-wrap items-center gap-2">
<span className="w-14 font-mono text-xs text-text-muted">
{variant}
</span>
{tones.map((tone) => (
<Badge key={tone} variant={variant} tone={tone}>
{tone}
</Badge>
))}
</div>
))}
</div>
)
}| Variant | Use for |
|---|---|
soft |
The default for tags and attributes. Tinted background, low contrast. |
solid |
One badge that must stand out in a dense row, such as “Beta” or “New”. Use sparingly. |
outline |
Secondary tags next to soft ones, and badges rendered as links. |
| Tone | Means |
|---|---|
neutral |
No judgment: an environment, a type, a tag. |
primary |
Highlighted by the product: a feature, a scope. |
success |
Positive or protected: enforced, verified. |
warning |
Needs attention: exposed, expiring. |
danger |
Harmful or broken: compromised, blocked. |
info |
Informational: preview, monitored. |
The shadcn variants default, secondary, destructive, ghost and link still exist and
ignore tone. Prefer the Zenox variants in new code.
Pill
pill rounds the badge fully. Use it for counts next to a label, and add tabular-nums so the
width holds as the number changes.
<div className="flex items-center gap-2 text-sm">
Open alerts
<Badge variant="soft" tone="danger" pill className="tabular-nums">
24
</Badge>
</div>With an icon
Mark the icon with data-icon="inline-start" or data-icon="inline-end"; the badge sizes it to
12px and tightens the padding on that side.
<>
<Badge variant="outline" tone="success">
<ShieldCheckIcon data-icon="inline-start" />
MFA enforced
</Badge>
<Badge variant="soft" tone="warning">
<GlobeIcon data-icon="inline-start" />
Exposed port 3389
</Badge>
</>As a link
A badge that filters a list or opens a record renders an <a> through the render prop, with
the label inside the link. The outline variant then gets a hover background.
function BadgeAsLink() {
return <Badge variant="outline" render={<a href="#usage">tag:pci-scope</a>} />
}Accessibility
- A badge is plain text. When its meaning depends on the column or the context (“24” next to “Open alerts”), keep that context visible or put it in the label.
- The tone is a visual hint. The label alone must say what the badge means.
API reference
Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.
Badge
Badge is a short label: a count, a tag, a category. For the state of a record use the StatusBadge pattern, and for a severity level SeverityBadge; both map the domain value to a tone for you. A removable filter is a FilterChip.
| Prop | Type | Default |
|---|---|---|
pill | boolean | nullFully rounded ends instead of the default small radius. | - |
render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>Allows you to replace the component's HTML element with a different tag, or compose it with another component. | - |
tone | "info" | "success" | "warning" | "neutral" | "primary" | "danger" | nullColor for the `soft`, `solid` and `outline` variants (`neutral` has no effect on `outline`). The other variants ignore it. | - |
variant | "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "soft" | "solid" | nullStyle. `default`, `secondary`, `destructive`, `outline`, `ghost` and `link` are complete on their own. `soft` (tinted fill) and `solid` (strong fill) take their color from `tone` and render uncolored without one. | - |