abdxdev/cn

Color Picker

A color swatch trigger with a spectrum, hex input, and the closest real color name picked for you in OKLab — plus search over ~32,000 color names.

Pick a shade, then tap one of the closest real color names — or search all ~32,000.

Rose Quartz
accent — pick
lining — pick
import { useState } from "react";
import { ColorPicker } from "@/components/color-picker";

export function ColorPickerDemo() {
  const [colors, setColors] = useState<Record<string, { name: string; hex: string }>>({
    finish: { name: "Rose Quartz", hex: "#f7cac9" },
  });

  return (
    <div className="flex flex-wrap gap-3">
      {["finish", "accent", "lining"].map((slot) => (
        <div key={slot} className="flex items-center gap-2 rounded-lg border px-2 py-1.5">
          <ColorPicker
            value={colors[slot]?.name ?? ""}
            hex={colors[slot]?.hex}
            onPick={(name, hex) => setColors((c) => ({ ...c, [slot]: { name, hex } }))}
          />
          <span className="text-xs">{colors[slot]?.name || `${slot} — pick`}</span>
        </div>
      ))}
    </div>
  );
}

Installation

npx shadcn@latest add https://abdxdev-cn.vercel.app/r/color-picker-ts.json

Usage

Keep the name and its hex together — the trigger paints hex, and value is what you store:

const [color, setColor] = useState({ name: "Rose Quartz", hex: "#f7cac9" });

<ColorPicker value={color.name} hex={color.hex} onPick={setColor} />;

Search is available too, if you'd rather pick from names directly:

<ColorPicker value="" onPick={(name, hex) => setColor({ name, hex })} />;

By default the popover suggests the 6 closest names. Change the count with maxSuggestions — the box holds 6 before it starts scrolling:

<ColorPicker value={color.name} hex={color.hex} onPick={setColor} maxSuggestions={10} />

How it works

  • Closest names are found in OKLab, where distance tracks how different two colors actually look. Plain RGB distance picks noticeably worse matches.
  • The curated list (~5,000 names, ~200 KB) loads the first time the popover opens. The full list (~32,000 names, ~1.2 MB) only loads when you focus the search box, because it has names the curated one lacks ("Rose Gold").
  • While you drag the spectrum, suggestions wait 150 ms before updating so the list holds still instead of flickering.
  • color-picker.css styles the spectrum to fill the popover; it uses two-class selectors so it beats react-colorful's runtime-injected styles.

API Reference

Prop

Type

On this page