# Status Badge

Shows the state of a record, such as new, in progress, resolved or failed, as a soft badge with an icon.

```tsx
import { CircleCheckIcon, CircleDotIcon, ClockIcon, LoaderIcon, TriangleAlertIcon } from "lucide-react"
import { StatusBadge } from "@zenoxai/ui/patterns/status-badge"

function StatusBadgeDemo() {
  return (
    <>
      <StatusBadge tone="neutral" icon={CircleDotIcon} label="New" />
      <StatusBadge tone="info" icon={LoaderIcon} label="In progress" />
      <StatusBadge tone="warning" icon={ClockIcon} label="Awaiting customer" />
      <StatusBadge tone="success" icon={CircleCheckIcon} label="Resolved" />
      <StatusBadge tone="danger" icon={TriangleAlertIcon} label="Failed" />
    </>
  )
}
```

## Usage

```tsx
import { CircleCheckIcon } from "lucide-react"

import { StatusBadge } from "@zenoxai/ui/patterns/status-badge"

export function ResolvedBadge() {
  return <StatusBadge tone="success" icon={CircleCheckIcon} label="Resolved" />
}
```

The library does not know your statuses. Keep one map in the app from each domain status to a
tone, an icon and a translated label, and pass the result in. Every screen that shows the
status then agrees on its color.

```tsx
import type { StatusTone } from "@zenoxai/ui/patterns/status-badge"

function getStatusTone(status: AlertStatus): StatusTone {
  switch (status) {
    case "new":
      return "neutral"
    case "triaging":
      return "info"
    case "awaiting_customer":
      return "warning"
    case "resolved":
      return "success"
    case "failed":
      return "danger"
  }
}
```

| Tone      | Use for                                     | Icon                |
| --------- | ------------------------------------------- | ------------------- |
| `neutral` | Not started, paused, archived.              | `CircleDotIcon`     |
| `info`    | Running or being worked on.                 | `LoaderIcon`        |
| `warning` | Waiting on someone, or close to a deadline. | `ClockIcon`         |
| `success` | Done, healthy, connected.                   | `CircleCheckIcon`   |
| `danger`  | Failed, broken, past a deadline.            | `TriangleAlertIcon` |

`label` is the translated text the user reads, never a raw enum (`awaiting_customer`) or an i18n
key. For the severity of a finding, use [Severity Badge](/patterns/severity-badge): severity is
a fixed scale, status is a workflow.

## Examples

### From a domain status

The table reads tone, icon and label from one map, keyed by the status the API returns.

```tsx
import { CircleCheckIcon, CircleDotIcon, ClockIcon, LoaderIcon } from "lucide-react"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@zenoxai/ui/components/table"
import { StatusBadge } from "@zenoxai/ui/patterns/status-badge"

function StatusBadgeFromStatus() {
  // In the app, this map lives next to the domain type, not in the view.
  const statusBadge = {
    new: { tone: "neutral", icon: CircleDotIcon, label: "New" },
    triaging: { tone: "info", icon: LoaderIcon, label: "Triaging" },
    awaiting_customer: {
      tone: "warning",
      icon: ClockIcon,
      label: "Awaiting customer",
    },
    resolved: { tone: "success", icon: CircleCheckIcon, label: "Resolved" },
  } as const

  const alerts = [
    { id: "ALR-2291", title: "Impossible travel sign-in", status: "new" },
    {
      id: "ALR-2287",
      title: "Malware detected on web-prod-03",
      status: "triaging",
    },
    { id: "ALR-2264", title: "Exposed S3 bucket", status: "awaiting_customer" },
    { id: "ALR-2250", title: "Brute force on VPN gateway", status: "resolved" },
  ] as const

  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>ID</TableHead>
          <TableHead>Alert</TableHead>
          <TableHead>Status</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {alerts.map((alert) => (
          <TableRow key={alert.id}>
            <TableCell className="font-mono">{alert.id}</TableCell>
            <TableCell>{alert.title}</TableCell>
            <TableCell>
              <StatusBadge {...statusBadge[alert.status]} />
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}
```

### Status dot

In dense lists where a badge per row is too heavy, `StatusDot` draws an 8px dot in the tone.
The dot is decorative: always put the status in text next to it. For inline status text
without a badge, `statusToneTextClass[tone]` gives the matching text color.

```tsx
import { StatusDot } from "@zenoxai/ui/patterns/status-badge"

function StatusBadgeDot() {
  return (
    <ul className="flex w-80 flex-col gap-2 text-sm">
      <li className="flex items-center gap-2">
        <StatusDot tone="success" />
        <span className="flex-1">CrowdStrike Falcon</span>
        <span className="text-text-secondary">Connected</span>
      </li>
      <li className="flex items-center gap-2">
        <StatusDot tone="warning" />
        <span className="flex-1">Microsoft Defender</span>
        <span className="text-text-secondary">Token expires soon</span>
      </li>
      <li className="flex items-center gap-2">
        <StatusDot tone="danger" />
        <span className="flex-1">AWS CloudTrail</span>
        <span className="text-text-secondary">Disconnected</span>
      </li>
      <li className="flex items-center gap-2">
        <StatusDot tone="neutral" />
        <span className="flex-1">Okta</span>
        <span className="text-text-secondary">Paused</span>
      </li>
    </ul>
  )
}
```

## Accessibility

- Color never carries the status alone. The label always renders; add an icon whenever the
  status sits among others that differ only by color.
- The icon is decorative (`aria-hidden`); the label is what screen readers read.
- `StatusDot` is hidden from assistive technology. Without visible text next to it, the status
  is lost for screen reader users and for users who cannot tell the colors apart.

## API reference

`import { ... } from "@zenoxai/ui/patterns/status-badge"`

### StatusBadge

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| icon | `LucideIcon` |  | Leading glyph. Give one whenever color alone would carry the meaning. |
| label (required) | `string` |  | Already-translated label. Never a raw enum or i18n key. |
| tone (required) | `"info" \| "success" \| "warning" \| "neutral" \| "danger"` |  | Color of the badge. |

### StatusDot

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| tone (required) | `"info" \| "success" \| "warning" \| "neutral" \| "danger"` |  |  |

