Badge
Small status/label pill. Located at apps/web/components/ui/badge.tsx.
Usage
<Badge>Active</Badge>
<Badge tone="success">Indexed</Badge>
<Badge tone="error">Failed</Badge>
<Badge tone="warning">Processing</Badge>
<Badge tone="info">Public</Badge>
Tones
| Tone | Fill | Text | Use |
|---|---|---|---|
| neutral (default) | bg-surface-2 | text-text-primary | Generic counts, roles |
| success | bg-success/10 | text-success | Active, ready, done |
| error | bg-error/10 | text-error | Failed, banned, deleted |
| warning | bg-amber-100 | text-amber-700 | Processing, pending |
| info | bg-accent/10 | text-accent | Public, new feature |
Size
Always small, fixed. ~18-20px tall. text-[10px] + font-semibold + uppercase optional for loud labels.
<Badge className="text-[10px] uppercase tracking-wider">SUPERADMIN</Badge>
With icon
<Badge className="gap-1">
<GlobeIcon /> Public
</Badge>
<Badge className="gap-1">
<LockIcon /> Private
</Badge>
Role-specific badges
Use the role-specific primitives instead of a generic Badge:
<PlatformRoleBadge role={user.platformRole} /><PositionBadge position={user.orgPosition} /><AccessTierBadge tier={grant.tier} />
These are wrappers around <Badge> with tones mapped per role. Keeps role styling consistent across the app.
Don't
- Don't use badge for primary content — it's metadata only
- Don't stack multiple badges without gap —
flex gap-1orgap-1.5 - Don't make badges clickable — they're labels, not buttons