Skip to content
weftGitHub

Badge

A small label for a status or a count.

SourcePackage @weft-js/warpPlayground

Preview

tsx
import { Badge } from '@weft-js/warp'export function Dot() {  return (    <>      <Badge tone="positive" dot>Live</Badge>      <Badge tone="info" dot>Building</Badge>      <Badge tone="critical" dot>Failed</Badge>      <Badge tone="neutral" dot>Paused</Badge>    </>  )}

Installation

npm install @weft-js/warp

Usage

tsx
import { Badge } from '@weft-js/warp'<Badge>Live</Badge>

Variants

soft by default.

tsx
import { Badge } from '@weft-js/warp'export function Emphasis() {  return (    <>      <Badge tone="positive">Status</Badge>      <Badge tone="positive" emphasis="solid">Status</Badge>      <Badge tone="positive" emphasis="outline">Status</Badge>    </>  )}type Status = 'Live' | 'Building' | 'Failed' | 'Paused'

Tones

Use tone to colour a badge by what it means.

tsx
import { Badge } from '@weft-js/warp'export function Tones() {  return (    <>{TONES.map(tone => <Badge key={tone} tone={tone}>Status</Badge>)}</>  )}type Status = 'Live' | 'Building' | 'Failed' | 'Paused'const TONES = ['neutral', 'accent', 'positive', 'caution', 'critical', 'info'] as const

Counts

count makes it round. srText says what is being counted.

tsx
import { Badge } from '@weft-js/warp'export function Count() {  return (    <>      <Badge count tone="accent" srText="unread comments">3</Badge>      <Badge count tone="critical" emphasis="solid" srText="failed deploys">12</Badge>      <Badge count emphasis="outline" srText="open reviews">99+</Badge>    </>  )}

Status in a list

Use dot with a tone to show each row's status at a glance.

tsx
import { Badge, Row, Stack, Text } from '@weft-js/warp'export function ProjectList() {  return (    <Stack gap="related" divided>      {PROJECTS.slice(2, 7).map(p => (        <Row key={p.id} justify="between" gap="group">          <Stack gap="hair"><Text>{p.name}</Text><Text role="caption" subtle>{p.owner}</Text></Stack>          <Badge tone={TONE_OF[p.status]} dot>{p.status}</Badge>        </Row>      ))}    </Stack>  )}type Status = 'Live' | 'Building' | 'Failed' | 'Paused'const PROJECTS: { id: string; name: string; owner: string; region: string; status: Status; deploys: number; uptime: number; latency: number; cost: number; updated: string }[] = [  { id: 'storefront', name: 'storefront', owner: 'Priya Raman', region: 'eu-west', status: 'Live', deploys: 412, uptime: 99.98, latency: 84, cost: 1240, updated: '2026-10-31' },  { id: 'checkout', name: 'checkout', owner: 'Tomás Oliveira', region: 'eu-west', status: 'Live', deploys: 288, uptime: 99.95, latency: 112, cost: 980, updated: '2026-10-31' },  { id: 'search-api', name: 'search-api', owner: 'Lena Fischer', region: 'us-east', status: 'Building', deploys: 196, uptime: 99.91, latency: 146, cost: 1610, updated: '2026-10-30' },  { id: 'billing', name: 'billing', owner: 'Mara Lindqvist', region: 'us-east', status: 'Live', deploys: 154, uptime: 99.99, latency: 73, cost: 720, updated: '2026-10-29' },  { id: 'mobile-bff', name: 'mobile-bff', owner: 'Sam Okafor', region: 'ap-south', status: 'Failed', deploys: 233, uptime: 99.42, latency: 208, cost: 860, updated: '2026-10-29' },  { id: 'notifier', name: 'notifier', owner: 'Jun Tanaka', region: 'eu-north', status: 'Live', deploys: 97, uptime: 99.97, latency: 58, cost: 310, updated: '2026-10-27' },  { id: 'reports', name: 'reports', owner: 'Noor Haddad', region: 'us-west', status: 'Paused', deploys: 41, uptime: 99.8, latency: 321, cost: 190, updated: '2026-10-22' },  { id: 'edge-cache', name: 'edge-cache', owner: 'Jun Tanaka', region: 'global', status: 'Live', deploys: 318, uptime: 100, latency: 21, cost: 1430, updated: '2026-10-31' },  { id: 'auth', name: 'auth', owner: 'Mara Lindqvist', region: 'eu-west', status: 'Live', deploys: 176, uptime: 99.99, latency: 66, cost: 540, updated: '2026-10-28' },  { id: 'ingest', name: 'ingest', owner: 'Lena Fischer', region: 'us-east', status: 'Live', deploys: 264, uptime: 99.93, latency: 131, cost: 2120, updated: '2026-10-30' },]const TONE_OF: Record<Status, 'positive' | 'info' | 'critical' | 'neutral'> = { Live: 'positive', Building: 'info', Failed: 'critical', Paused: 'neutral' }

A count on a button

Use count to show a number badge inside a button.

tsx
import { Badge, Button } from '@weft-js/warp'export function OnAButton() {  return (    <Button emphasis="outline" tone="neutral" icon="bell">Alerts <Badge count tone="critical" emphasis="solid" srText="new">2</Badge></Button>  )}

When to use

Use it for

  • Saying what state something is in
  • A count on a button or a heading

Reach for something else

  • Tag, when people wrote the label themselves
  • Chip, when pressing it should do something
  • LiveStatus, when it shows a live connection

Playground

Tone
Emphasis
import { Badge } from '@weft-js/warp'<Badge tone="positive" dot>Live</Badge>

Accessibility

  • The words carry the status, so it never depends on colour.
  • A count alone means little to a screen reader: use srText.

API Reference

PropTypeDefaultDescription
toneTone—What it means.
emphasis"solid" | "soft" | "outline"—soft, solid or outline.
countbooleanfalseRound, for a number.
dotbooleanfalseA status dot before the label.
srTextstring—Extra words for screen readers, like "unread comments".
childrenunknown—What it contains.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="badge"] [data-part="sr-only"]

sr-only

RelatedTagChipLive status