Badge
Small status and metadata component used to label, categorize, or highlight information in PyColors UI.
Compact metadata for product interfacesLink to section
The Badge component is a compact, non-interactive primitive used to display short information.
Use it for:
- status
- category
- count
- plan label
- metadata
- product state
- feature availability
Badges are lightweight, semantic, and aligned with PyColors design system tokens.
They are designed for metadata, not actions.
Core idea
A Badge communicates state or context. It should not replace a Button.
ImportLink to section
import { Badge } from "@pycolors/ui";Basic usageLink to section
import { Badge } from "@pycolors/ui";
export function BasicBadge() {
return <Badge>Default</Badge>;
}Badges inherit their colors from semantic tokens and adapt to light and dark mode.
When to use BadgeLink to section
Use Badge when the label helps the user understand context without adding heavy visual hierarchy.
Metadata
Status
Grouping
VariantsLink to section
Use variants to convey meaning or status.
import { Badge } from "@pycolors/ui";
export function BadgeVariants() {
return (
<div className="flex flex-wrap gap-2">
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="muted">Muted</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="destructive">Destructive</Badge>
</div>
);
}Available variantsLink to section
| Variant | Purpose |
|---|---|
default | Primary or neutral label |
secondary | Supporting information |
muted | Low-emphasis metadata |
outline | Neutral bordered label |
success | Positive or completed state |
warning | Caution or attention required |
destructive | Error or critical state |
Design rule
Prefer muted and outline for metadata. Reserve semantic state variants for actual product states.
SizesLink to section
Use size to control density and hierarchy.
import { Badge } from "@pycolors/ui";
export function BadgeSizes() {
return (
<div className="flex items-center gap-2">
<Badge size="sm">Small</Badge>
<Badge size="md">Default</Badge>
<Badge size="lg">Large</Badge>
</div>
);
}Available sizesLink to section
| Size | Purpose |
|---|---|
sm | Dense metadata, tables, compact lists |
md | Default badge size |
lg | Emphasized label or standout metadata |
Density rule
Use sm in tables and dense product views. Use md for most UI surfaces. Use lg sparingly.
With left iconLink to section
Badges can include a left icon when the icon reinforces status, type, or category.
import { Badge } from "@pycolors/ui";
import { CheckCircle } from "lucide-react";
export function BadgeWithLeftIcon() {
return (
<Badge variant="success">
<CheckCircle className="size-3" aria-hidden="true" />
Active
</Badge>
);
}Icon rule
Icons should reinforce meaning. The text must still explain the state.
With right iconLink to section
Use a right icon when the badge points to a related surface, external context, or lightweight next step.
import { Badge } from "@pycolors/ui";
import { ArrowRight } from "lucide-react";
export function BadgeWithRightIcon() {
return (
<Badge variant="outline">
Docs
<ArrowRight className="size-3" aria-hidden="true" />
</Badge>
);
}Placement rule
Use left icons for state or identity. Use right icons for direction, continuation, or linked context.
As childLink to section
Use asChild when the badge should render as another semantic element.
import { Badge } from "@pycolors/ui";
export function BadgeAsChild() {
return (
<Badge asChild>
<a href="/docs">Docs</a>
</Badge>
);
}Interaction rule
Only use interactive badges when the underlying element is semantic, such as an anchor or button. If it triggers an important action, use Button instead.
Usage patternsLink to section
Choose the message
Decide what the badge communicates: status, category, role, version, count, or plan.
Pick the lowest useful emphasis
Start with muted or outline. Move to semantic variants only when the state needs clear meaning.
Keep the label short
Badges work best with short labels: one or two words.
Avoid turning metadata into actions
A badge should not become a primary interaction. Use Button for actions.
Badge vs Button vs AlertLink to section
| Situation | Use |
|---|---|
| Show a small status | Badge |
| Show a category or plan label | Badge |
| Trigger an action | Button |
| Show persistent feedback or warning | Alert |
| Confirm temporary background action | Toast |
Decision rule
Badge communicates context. Button triggers intent. Alert explains important feedback.
APILink to section
| Prop | Type | Default | Description |
|---|---|---|---|
variant | BadgeVariant | "default" | Visual style |
size | BadgeSize | "md" | Badge size |
asChild | boolean | false | Render via Radix Slot |
className | string | — | Additional Tailwind classes |
The Badge extends standard HTML span props:
React.HTMLAttributes<HTMLSpanElement>TypeScript typesLink to section
export type BadgeVariant =
| "default"
| "secondary"
| "muted"
| "outline"
| "success"
| "warning"
| "destructive";
export type BadgeSize = "sm" | "md" | "lg";AccessibilityLink to section
- Badges are non-interactive by default.
- Do not use a badge as a button.
- Do not rely on color alone to convey meaning.
- Icons must be supplementary, not the only indicator.
- Use
aria-hidden="true"for decorative icons. - When interactive, use
asChildwith a semantic element such asaorbutton.
Prefer / avoidLink to section
Prefer
- short labels
- semantic variants for real status
mutedoroutlinefor metadata- icons as supporting context only
- consistent badge usage across tables and cards
Avoid
- using badges as primary actions
- long sentence-like badge text
- too many badges in one panel
- color-only meaning
- inventing one-off badge colors locally