<!-- Protocore Design System — Badge -->
# Badge

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/badge`
- **Status:** stable
- **Platforms:** web, mobile
- **Import:** `import { Badge } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/badge

> A static, sentence-case status indicator with a tone-tinted fill — never interactive, never color-only.

## Badge vs Tag vs Chip vs Button

These four look adjacent but encode different things, and the system keeps them apart by **case and type family** so a glance tells you what you can do with each:

- **Badge** — *status*. Sentence-case **sans** on a tone tint, no border, not interactive. It answers *what state is this row in?* (Settled, Failed, Syncing).
- **Tag** — *metadata*. **Mono**, as-typed, muted, optionally bordered. It answers *what is this labelled with?* (`region:eu-central-1`, a commit sha). Static, or copy-on-click.
- **Chip** — *an interactive filter*. Mono **UPPERCASE**, a ghost outline that inverts to the primary fill when selected. It answers *do you want to filter by this?* — it toggles.
- **Button** — *an action*. Mono UPPERCASE control-height; it *does* something.

Rule of thumb: if it describes a state, it's a Badge; if it's a value or key you might copy, it's a Tag; if clicking it changes the view, it's a Chip; if clicking it performs an operation, it's a Button.

## Mobile (React Native)

**Preview.** `@protocore/pds-mobile` ships the React Native sibling of **Badge**. It mirrors the web API where React Native allows; the package is a **preview** with no device-level QA yet, so pin it and expect small changes.

Import it from the mobile package (not `@protocore/pds`), inside a `<PdsProvider>` — there is no stylesheet, so `style` (a `ViewStyle`) replaces `className` and every value comes from the theme:

```tsx
import { Badge } from "@protocore/pds-mobile";
```

**Parity with web.** A static, non-interactive `View` — sentence-case sans, tone tint, no border, same as web.

- The tone tint is derived from the single tone colour (a low-alpha overlay) rather than web's dedicated `--pds-color-<tone>-bg` token, so the exact tint can differ by a hair.
- Never color-only: always pass a text label (optionally `dot` or an `icon`).

```tsx
<Badge tone="success" dot>Live</Badge>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `dot` | `boolean` | no | `false` | Show a small square status dot before the label. |
| `icon` | `ReactNode` | no | — | Optional leading icon slot (any `ReactNode`), shown after the dot. |
| `style` | `CSSProperties` | no | — | — |
| `tone` | `enum` | no | `neutral` | Status tone — drives the tint background and foreground. Defaults to `neutral`. |

## Examples

### Basics

Give the Badge a `tone` and a text label. It renders sentence-case sans on a soft tint of the tone — a quiet, non-interactive read of one row's state.

```tsx
import { Badge, Stack } from "@protocore/pds";

export default function BadgeBasics() {
  return (
    <Stack direction="row" gap={2} align="center" wrap>
      <Badge tone="success">Active</Badge>
      <Badge tone="warning">Degraded</Badge>
      <Badge tone="danger">Failed</Badge>
      <Badge tone="info">Syncing</Badge>
      <Badge tone="neutral">Draft</Badge>
    </Stack>
  );
}
```

### Tones

Five semantic tones — `success`, `warning`, `danger`, `info`, `neutral`. Pick the tone that matches the *meaning* of the state, not the one that looks best. `neutral` is the default and the right choice for states that carry no urgency (draft, archived).

```tsx
import { Badge, DefinitionList } from "@protocore/pds";

// Each tone maps to one meaning — reach for the tone that matches the state,
// never the one that looks nice.
export default function BadgeTones() {
  return (
    <DefinitionList labelWidth={120}>
      <DefinitionList.Item term="success">
        <Badge tone="success">Settled</Badge>
      </DefinitionList.Item>
      <DefinitionList.Item term="warning">
        <Badge tone="warning">Pending review</Badge>
      </DefinitionList.Item>
      <DefinitionList.Item term="danger">
        <Badge tone="danger">Reversed</Badge>
      </DefinitionList.Item>
      <DefinitionList.Item term="info">
        <Badge tone="info">In flight</Badge>
      </DefinitionList.Item>
      <DefinitionList.Item term="neutral">
        <Badge tone="neutral">Archived</Badge>
      </DefinitionList.Item>
    </DefinitionList>
  );
}
```

## Usage

**Do**

- Always pair the tone with a text label (or an icon) — colour is a reinforcement, never the sole signal.
- Map each tone to a single meaning across the product: danger = failed/reversed, warning = needs attention, success = terminal-good.
- Keep the label to one or two words in sentence case ("In flight", not "IN FLIGHT").
- Use `neutral` for states with no urgency rather than borrowing a status hue for decoration.

**Don't**

- Don't make a Badge clickable — reach for Chip (filter) or Button (action) instead.
- Don't use the accent/brand colour as a badge fill; status tones only.
- Don't encode a mono identifier or key in a Badge — that's a Tag.
- Don't stack four different tones in one row hoping colour alone communicates rank.

## Accessibility

**Notes**

- Badge renders a plain `<span>` with no interactive semantics — it is decoration around a text label, so screen readers announce the label text directly.
- The `dot` and `icon` slots are `aria-hidden` — they must never carry information the text label doesn't already state.
- Tone is expressed as a background tint that meets contrast against its foreground; because status is always accompanied by text, the badge remains legible to colour-blind and monochrome readers.

## Related

`tag`, `role-chip`, `status-dot`, `env-badge`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
