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

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

> An icon in a sized, sharp square container with a filled / light / outline / ghost treatment.

## When to use it

`ThemeIcon` gives an icon a visible container — for feature rows, menu leading marks, callout headers, empty-state glyphs. It is the framed cousin of **Icon**, which only sizes a bare glyph. When you need a *status word*, use a **Badge**; when you need a *user's picture*, use an **Avatar**.

The container is decorative brand chrome, so its accent/tone fill is fine — but the meaning must live in adjacent text or the `label`. Keep the icon child a 1em `currentColor` SVG so the variants' foreground colours apply.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | no | — | The SVG icon to render (drawn at 1em, `currentColor`). |
| `className` | `string` | no | — | — |
| `label` | `string` | no | — | Accessible label. When set the container becomes `role="img"` and announces this text; omit it for a purely decorative icon (then `aria-hidden`). |
| `size` | `enum` | no | `md` | Box size: sm 24 · md 32 · lg 40. |
| `style` | `CSSProperties` | no | — | — |
| `tone` | `enum` | no | — | Colour family — omit for the brand accent, set a status tone to recolour. |
| `variant` | `enum` | no | `filled` | Visual treatment. |

## Examples

### Variants

`ThemeIcon` frames an icon in a sharp square. Four treatments: `filled` (solid), `light` (tint wash), `outline` (hairline border), and `ghost` (bare). The default `filled` with no tone uses the brand accent.

```tsx
import { ThemeIcon, Stack } from "@protocore/pds";
import { Rocket } from "lucide-react";

export default function ThemeIconVariants() {
  return (
    <Stack direction="row" gap={4} align="center">
      <ThemeIcon variant="filled" label="Filled">
        <Rocket />
      </ThemeIcon>
      <ThemeIcon variant="light" label="Light">
        <Rocket />
      </ThemeIcon>
      <ThemeIcon variant="outline" label="Outline">
        <Rocket />
      </ThemeIcon>
      <ThemeIcon variant="ghost" label="Ghost">
        <Rocket />
      </ThemeIcon>
    </Stack>
  );
}
```

### Tones

Set a `tone` to recolour the container to a status family — a red filled square for a failure, an amber light wash for a warning. Every variant honours the tone.

```tsx
import { ThemeIcon, Stack } from "@protocore/pds";
import { CircleCheck, TriangleAlert, CircleX, Info } from "lucide-react";

export default function ThemeIconTones() {
  return (
    <Stack direction="row" gap={4} align="center">
      <ThemeIcon tone="success" variant="light" label="Settled">
        <CircleCheck />
      </ThemeIcon>
      <ThemeIcon tone="warning" variant="light" label="Pending review">
        <TriangleAlert />
      </ThemeIcon>
      <ThemeIcon tone="danger" variant="filled" label="Reversed">
        <CircleX />
      </ThemeIcon>
      <ThemeIcon tone="info" variant="outline" label="Syncing">
        <Info />
      </ThemeIcon>
    </Stack>
  );
}
```

## Usage

**Do**

- Feed it a 1em `currentColor` SVG so variant colors apply.
- Add a `label` when the icon alone conveys meaning.
- Match the `tone` to the meaning of the row it leads.

**Don't**

- For a status word, use a Badge.
- Give a meaningful icon a label or accompanying text.
- Keep the corners square; the square is the brand.

## Accessibility

**Notes**

- Decorative by default: without a `label` the container is `aria-hidden` so it adds no noise to the accessibility tree.
- With a `label` it becomes `role="img"` with that accessible name — use this only when the icon alone conveys meaning.
- Colour is never the sole signal — pair a toned icon with a text label in the surrounding layout.

## Related

`icon`, `badge`, `avatar`, `status-dot`

---

© 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/
