Chroma Panel

Search documentation

Find a page or section

Brand palette

View as Markdown

Replace or extend the built-in swatch sets.

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.

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:

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 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():

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 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:

<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 page.