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

- **Category:** Inputs (`inputs`)
- **Slug:** `inputs/color-swatch`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { ColorSwatch } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/inputs/color-swatch

> A single sharp color square — the primitive the color picker, color input, and accent pickers reuse.

## When to use it

**ColorSwatch** is a display primitive: a labelled color chip. Use it to preview a stored color, to build an **accent / theme picker** (a row of clickable swatches), or as the leading affordance inside a **ColorInput**. It is not a status indicator — for a small colored status dot next to a label, use **StatusDot**, whose color carries semantic tone. A swatch's color is arbitrary content, never a `success`/`danger` signal.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `aria-label` | `string` | no | — | Accessible label — required when interactive (icon-only affordance). |
| `checkered` | `boolean` | no | — | Show a checkerboard behind the color so alpha/transparency reads through. |
| `className` | `string` | no | — | — |
| `color` | `string` | yes | — | The color to display — any CSS color string (`#3fcf8e`, `rgb(...)`, `transparent`). |
| `onClick` | `MouseEventHandler<HTMLElement>` | no | — | Click handler — when provided the swatch renders as a real `<button>`. |
| `selected` | `boolean` | no | — | Draw the accent selection ring around the swatch. |
| `size` | `enum` | no | `md` | Square size: `sm` (16) · `md` (24, default) · `lg` (32). |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Palette

Pass any CSS color to `color`. Swatches are square and sharp — no rounded corners — sized `sm` (16), `md` (24), or `lg` (32).

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

const brand = [
  { name: "green", hex: "#3fcf8e" },
  { name: "blue", hex: "#2a6fdb" },
  { name: "red", hex: "#e8533f" },
  { name: "amber", hex: "#c9a227" },
  { name: "violet", hex: "#a855f7" },
  { name: "neutral", hex: "#8b8b8b" },
];

export default function Demo() {
  return (
    <Stack gap={3} direction="row" align="center" wrap>
      {brand.map((c) => (
        <Stack key={c.name} gap={1} align="center">
          <ColorSwatch color={c.hex} size="lg" />
          <Text size="sm" color="muted" mono>
            {c.hex}
          </Text>
        </Stack>
      ))}
    </Stack>
  );
}
```

### Selectable

Give a swatch an `onClick` and it renders as a real `<button>` with a pointer cursor and hover feedback. Mark the active one with `selected` to draw the accent ring. Interactive swatches require an `aria-label`.

```tsx
import { useState } from "react";
import { ColorSwatch, Stack, Text } from "@protocore/pds";

const accents = ["#3fcf8e", "#2a6fdb", "#e8533f", "#c9a227", "#a855f7"];

export default function Demo() {
  const [accent, setAccent] = useState(accents[0]);

  return (
    <Stack gap={3}>
      <Text size="sm" color="muted">
        Deployment accent: <span style={{ fontFamily: "var(--pds-font-mono)" }}>{accent}</span>
      </Text>
      <Stack gap={2} direction="row" role="radiogroup" aria-label="Accent color">
        {accents.map((c) => (
          <ColorSwatch
            key={c}
            color={c}
            size="lg"
            selected={c === accent}
            aria-label={c}
            onClick={() => setAccent(c)}
          />
        ))}
      </Stack>
    </Stack>
  );
}
```

## Do & don't

**Do**

- Give every interactive swatch an `aria-label` — the color is the only content.
- Use `selected` to mark the chosen swatch in a picker row.
- Turn on `checkered` when the color may be translucent.
- Reuse it as the primitive inside custom color pickers.

**Don't**

- Don't use a swatch for status — use StatusDot (semantic tone).
- Don't add `onClick` without an accessible label.
- Don't round the corners; swatches are square.
- Don't distinguish swatches by color alone — pair with a text value.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Focus the next interactive swatch (button variant only). |
| `Enter / Space` | Activate the focused swatch. |

**Notes**

- Without `onClick` the swatch is a non-interactive `<span>` — no pointer, no hover, no tab stop (affordance honesty).
- With `onClick` it becomes a `<button>` and requires an `aria-label`, since the color square carries no text.
- The selection ring is drawn with `outline`, so it never shifts surrounding layout.

## Related

`color-picker`, `color-input`, `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/
