# Status Indicator

> State as shape and colour together, so it reads at a glance and without colour vision.

Component · Foundations · Pro kit · [Live page](https://ui.twentyfirst.media/pro/components/StatusIndicator/)

State as shape and colour together, so it reads at a glance and without colour vision.

Props: `status` ("ok" | "running" | "signal" | "warn" | "danger" | "idle"), `label`, `size` ("sm"). `StatusShape` is the bare shape.

| status | shape | token | typical words |
| --- | --- | --- | --- |
| ok | dot | `ok` | Done, Online, Valid, Booked |
| running | pulsing dot | `info` | Working, Syncing |
| signal | diamond | `signal` | Waiting for approval, Needs a human |
| warn | triangle | `warn` | Paused · budget, Expiring |
| danger | square | `danger` | Failed, Offline |
| idle | ring | `idle` | Ready, Inactive |

- Always shape plus a word; drop the word only in dense columns whose header already names the state.
- Only `signal` may draw attention unasked. Warnings and errors stay in their own area and never animate.
- Badges use the same shapes: success dot, info dot, highlight diamond, warning triangle, danger square, neutral ring. Badge tones also accept the status names (ok, running, signal, warn, idle).

## Example

```tsx
import * as React from "react";
import { Badge, StatusIndicator } from "@twentyfirstmedia/pro";
import type { Status, Tone } from "@twentyfirstmedia/pro";

const S: [Status, string][] = [
  ["ok", "Done"],
  ["running", "Working"],
  ["signal", "Waiting for approval"],
  ["warn", "Paused · budget"],
  ["danger", "Failed"],
  ["idle", "Ready"],
];
export default function Preview() {
  return (
    <div
      className="tf-panel"
      style={{
        gap: 24,
      }}
    >
      <div
        className="tf-grid"
        style={
          {
            "--cols": "repeat(3, minmax(0, 1fr))",
            gap: 16,
          } as React.CSSProperties
        }
      >
        {S.map((s) => (
          <StatusIndicator key={s[0]} status={s[0]} label={s[1]} />
        ))}
      </div>
      <div className="tf-row">
        {(
          [
            ["success", "Live"],
            ["info", "Pending"],
            ["highlight", "Needs review"],
            ["warning", "Expiring"],
            ["danger", "Overdue"],
            ["neutral", "Draft"],
          ] as [Tone, string][]
        ).map((b) => (
          <Badge key={b[0]} tone={b[0]}>
            {b[1]}
          </Badge>
        ))}
      </div>
    </div>
  );
}
```

## Props

### Badge

| Prop | Type | Notes |
| --- | --- | --- |
| `tone?` | `Tone` |  |
| `dot?` | `boolean` |  |
| `live?` | `boolean` |  |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### StatusIndicator

| Prop | Type | Notes |
| --- | --- | --- |
| `status` | `Status` | Required |
| `label?` | `ReactNode` |  |
| `size?` | `"sm"` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
