# Brand palette

> Put your own brand swatches in the React color picker with the palettes prop, and use defaultPalettes to extend the built-in sets instead of replacing them.

Source: https://chroma-panel.jscrate.dev/react/recipes/brand-palette
Last updated: 2026-09-18

Most products do not want anyone choosing any color. Give the palettes mode your
own swatch sets when the answer should come from a design system, a brand guide
or a customer's theme, and the picker becomes a short list of approved choices.
Fill in the names while you are there: they are what the search box matches and
what a screen reader reads out.

```tsx
import { ChromaPanel, type ColorPalette } from "chroma-panel";
import "chroma-panel/style.css";

const BRAND: ColorPalette[] = [
  {
    name: "Core",
    colors: [
      { color: "#0b1b3a", name: "Ink" },
      { color: "#3366cc", name: "Signal" },
      { color: "#f5f7fb", name: "Paper" },
    ],
  },
  {
    name: "Status",
    colors: ["#2f9e44", "#f08c00", "#e03131"],
  },
];

export function BrandPicker() {
  return (
    <ChromaPanel
      modes={["palettes", "wheel"]}
      palettes={BRAND}
      defaultValue="#3366cc"
    />
  );
}
```

Listing `palettes` first in `modes` makes it the tab the panel opens on, because
the first mode is the default one. Drop `"wheel"` from the list to leave the
brand set as the only way to pick.

## The shape

`palettes` takes a `ColorPalette[]`. A palette is a group with a `name` and its
`colors`:

```tsx
interface ColorPalette {
  name: string;
  colors: (string | { color: string; name?: string })[];
}
```

A color is either a bare string or an object carrying the color and an optional
name. Both forms can sit in the same group, as `BRAND` above does. The string
goes through the same parser as `value`, so `"#3366cc"`, `"rgb(51 102 204)"` and
`"hsl(220 60% 50%)"` all work.

Each group renders as a [SwatchGrid](https://chroma-panel.jscrate.dev/react/components/swatch-grid) under a
heading, and every swatch is a real button. Its accessible name is the `name`
you gave it, falling back to the color string, so a reader hears "Ink" rather
than "number 0b1b3a". The swatch matching the current color carries
`aria-pressed`.

Search filters within each group and then drops groups with nothing left, so a
query that matches one group shows only that group. It matches the color string
and the name, both case-insensitively, which is the second argument for naming
swatches.

## Extending rather than replacing

Passing `palettes` replaces the three built-in groups outright. To keep them and
put your own first, spread `defaultPalettes()`:

```tsx
import { ChromaPanel, defaultPalettes } from "chroma-panel";

<ChromaPanel
  modes={["palettes"]}
  palettes={[...BRAND, ...defaultPalettes()]}
/>;
```

`defaultPalettes()` builds a fresh array on every call, so you can reorder or
filter the result without affecting what the panel falls back to.

> **defaultPalettes is on the main entry only**
>
> It is exported from `chroma-panel`, which registers all five modes. The
> `chroma-panel/panel` and `chroma-panel/palettes` entries do not export it —
> see [entry points](https://chroma-panel.jscrate.dev/react/utils/entry-points) for what each one carries.

## A palette-only picker

For some products the approved set is the whole picker. Pass a single mode and
the tab bar has nothing left to switch between:

```tsx
<ChromaPanel modes={["palettes"]} palettes={BRAND} showRecentColors={false} />
```

`showRecentColors={false}` also clears the recent swatches out of the footer,
which otherwise let someone return to a color that is no longer on the list.

`showAlpha` is worth knowing about here for what it does not do: the opacity
slider and the alpha field belong to the wheel and sliders modes, so a
palettes-only picker never shows one either way. The mode's id, its search box
and the built-in groups are covered on the
[palettes mode](https://chroma-panel.jscrate.dev/react/modes/palettes) page.
