A research project exploring the interaction design of a palette-aware color picker — what happens when the tool itself shows you how your colors relate to each other?
The canvas maps a color space onto a plane — as you add colors, it splits into regions showing which color is closest at every point. A color that's far from all others claims a large region; one that's close to a neighbor gets squeezed into a sliver. There's no predetermined weight factor — it emerges naturally from how your colors are distributed, measured by a perceptual distance metric (like OKLab or ΔE2000) from color science. Drag a color and watch the territories shift in real time.
| C | Toggle pick mode (add color on next click) |
| Cmd / Ctrl + click | Add a new color |
| Double-click | Add a new color (hold to drag-adjust) |
| Click | Select the closest color under cursor |
| Drag | Move the selected color |
| Cmd / Ctrl + Z | Undo |
| Delete / Backspace | Remove color under cursor (canvas) or selected color |
| Esc | Cancel drag or exit pick mode |
| Alt / Option | Reveal raw color space under hovered region |
| Shift + Alt / Option | Isolate color (flat region stays, rest shows raw) |
| Scroll / two-finger swipe | Adjust position slider (3rd axis) |
Double-click the canvas, or hold Cmd / Ctrl and click to add a new color. You can also press C to enter pick mode, then click to place a color. Hold after double-clicking or Cmd-clicking to drag and adjust the color before releasing.
Click a region on the canvas or a swatch to select a color. Drag on the canvas to move the selected color to a new position. Press Esc to cancel a drag and restore the original color.
Hover a swatch and click the × button, or press Delete / Backspace — this removes the color under the cursor when hovering the canvas, or the selected color otherwise.
Hold Alt / Option while hovering the canvas or a swatch to reveal the raw color space under that color's region. Add Shift to invert — isolate the color so only its region stays flat while the rest reveals the raw color space. Both work while dragging too.
Type or paste hex values into the text field at the bottom — comma or
space separated (e.g. #ff0000, #00ff00, #0000ff). The
palette updates with all valid colors. Clearing the field removes all
colors.
The slider controls the third dimension of the color space — the one not shown on the canvas. Click the axis label next to it to cycle through axes (e.g. H, S, L). You can also scroll or two-finger swipe on the canvas to adjust it.
The color space used to render the canvas. Different models emphasize different relationships — OKHsl is perceptually uniform, HSL is the classic web model, OKLab shows perceptual lightness vs. chroma.
How "closeness" between colors is measured when splitting the canvas into regions. OKLab is a good perceptual default. ΔE2000 matches human vision more precisely but is slower. RGB is naive but fast.
Draws a thin border between palette regions so you can see boundaries more clearly.
When adding a new color via Cmd / Ctrl + drag, the new color's region reveals the raw color space underneath instead of the flat palette color, so you can see exactly where you're placing it.
When enabled (the default), the palette is automatically sorted so visually similar colors sit next to each other. Sorting uses a trained ML model and only activates with more than two colors. You can turn it off in Settings if you want to keep your own ordering.
Hides out-of-gamut colors that can't be displayed on a standard screen. Only has an effect on color models that go beyond sRGB — like OKLab, OKLCH, or CIELab. Models that are inherently bound to sRGB (HSL, HSV, RGB) are unaffected.
Your entire palette and all settings are stored in the URL. Bookmark it to save your work, or share the link with someone to give them the exact same view.
Token Beam is a real-time sync protocol for design tokens. It lets you beam your palette directly into tools like Figma, Aseprite, Blender, or any app with a Token Beam plugin. In Send mode, a session token is generated — copy it and paste it into the receiving tool. In Receive mode, paste a token from an external source to pull colors in.
Built with palette-shader, culori & colorsort-js — GitHub — pickypalette.color.pizza
If you find this useful, consider buying me a coffee.