# Badge

A count or a state, set in mono so it reads as metadata.

- Group: Display
- Import: `import { Badge } from '@misoto22/folio'`
- Page: https://ui.misoto22.com/components/badge/
- Related: tag, status-pill

## When to reach for it

One fact about one record. If it names what something is ABOUT, that is a Tag.

## Anatomy

- **Chip** (required) — The <span>: inline-flex on the --radius-sm corner, mono at 12px with wide tracking. The mono face is the whole signal — it is what tells a reader this is metadata rather than a word of the sentence it sits in.
- **Ground** (required) — The tone’s fill — --stone for neutral, the soft tint of --ok, --warn or --danger for the three status tones, and nothing at all for outline.
- **Border** (required) — Always drawn, and transparent for every tone but outline, so the box reserves the pixel either way and swapping tone at runtime moves nothing beside it.
- **Content** (required) — children, with a 6px gap between them — so a StatusDot or a Kbd set beside the text spaces itself without a wrapper.

## Best practices

### Do

- Leave tone at neutral unless the badge names a STATE: the three status tones are the only chroma this system spends, and a badge that is red because the page wanted red is the thing the scale exists to prevent.
- Reach for outline when the badge sits on --stone already — every other tone fills its own ground, and a neutral badge on stone is a chip with no visible edge at all.
- Keep it to a count, a word, or a short state. It is 12px mono sized for one line, so a phrase in it is prose set in the metadata face and wraps inside a box that was never given a second line.

### Don’t

- A row of them is a Tag list drawn in the wrong component: Badge has no active state, so the filter bar it turns into cannot show which facet is on.
- A neutral Badge and an inactive Tag are the same corner, the same padding and the same 12px mono, separated by one ink step — so a row that mixes states and topics reads as one undifferentiated run of chips.
- There is no dismiss affordance here. A × written into children is text inside the accessible name, so the badge is announced as “beta ×” and the close it advertises does not exist.

## Accessibility

- Not interactive. A badge with an onClick is a control a keyboard cannot reach.
- The status tones double their colour with words, so the meaning survives monochrome and colour-blindness.

## Badge

A count, a state, a small inline marker. Mono and small, so it reads as metadata rather than as content. A badge is not interactive — if it can be clicked or dismissed it is a `Tag` or a button, and giving this one an `onClick` produces a control a keyboard cannot reach.

### Props

- `children` (required) — `ReactNode`.
- `tone` — `BadgeTone` default `'neutral'`. `neutral` is the default and the right answer nearly always. The three status tones are the system's only chroma and are bound to STATE — a badge that is red because the design wanted a red badge is the thing this scale exists to prevent.

Also accepts: `HTMLAttributes<HTMLSpanElement>`.

## Example — tones

```tsx
import { Badge } from '@misoto22/folio'

<div className="flex flex-wrap items-center gap-2">
  <Badge>12</Badge>
  <Badge tone="outline">Draft</Badge>
  <Badge tone="success">Deployed</Badge>
  <Badge tone="warning">Degraded</Badge>
  <Badge tone="danger">Failed</Badge>
</div>
```

## Example — with a status dot

```tsx
import { Badge, StatusDot } from '@misoto22/folio'

<div className="flex flex-wrap items-center gap-2">
  <Badge tone="success">
    <StatusDot size="sm" pulse={false} /> Deployed
  </Badge>
  <Badge tone="warning">
    <StatusDot size="sm" tone="warning" pulse={false} /> Degraded
  </Badge>
  <Badge tone="danger">
    <StatusDot size="sm" tone="danger" pulse={false} /> Failed
  </Badge>
</div>
```

## Example — on a stone ground

```tsx
import { Badge } from '@misoto22/folio'

<div className="flex flex-wrap items-center gap-2 rounded-(--radius) bg-(--stone) p-4">
  <Badge>Neutral</Badge>
  <Badge tone="outline">Outline</Badge>
</div>
```
