Color Picker
An OKLCH-based color picker with a 2D lightness/chroma plane, hue slider, hex input, and optional preset chips. Renders inline or in a Radix Popover.
Default (popover)
The default mode="popover" renders a small trigger swatch that opens the picker on click. Use this for inline form fields and tight layouts.
Inline
mode="inline" renders the full picker in place — useful in side panels, theme creators, and any UI that wants the picker permanently visible.
With presets
Provide a presets array of hex strings to render quick-pick chips below the hex input.
Disabled
Installation
npx visor add color-pickerThis copies three files into your project:
components/ui/color-picker/color-picker.tsx— the componentcomponents/ui/color-picker/color-picker.module.css— the stylescomponents/ui/color-picker/oklch.ts— OKLCH math wrappers that re-export the validated engine from@loworbitstudio/visor-theme-engine
Usage
import { ColorPicker } from '@/components/ui/color-picker/color-picker';
<ColorPicker
defaultValue="#3b82f6"
onChange={(hex) => console.log('preview:', hex)}
onCommit={(hex) => console.log('committed:', hex)}
aria-label="Brand color"
/>onChange fires on every continuous interaction (pointer drag, keyboard nudge, hex typing). onCommit fires on pointer-up, popover close, and Enter — use it to debounce expensive consumers (theme regeneration, network writes).
The component is theme-agnostic: every surface, border, focus ring, and shadow resolves through Visor semantic tokens. Canvas pixels (the lightness/chroma plane and hue strip) are computed colors, not theme surfaces.
API Reference
ColorPickerProps
No props data available for “color-picker”.
Accessibility
- Root is a
role="group"with anaria-label(defaults to"Color picker") - The lightness/chroma plane is
role="slider"with anaria-valuetextdescribing L and C - The hue track is
role="slider"witharia-valuemin=0,aria-valuemax=360, andaria-valuenow - Keyboard support:
- Plane: Arrow keys nudge L/C by 0.01; Shift+Arrow by 0.05; PgUp/PgDn jump by 0.1
- Hue: Arrow keys nudge H by 1°; Shift+Arrow by 15°; Home/End jump to 0°/360°
- The hex input is a labeled
<input type="text">and marksaria-invalidwhile a parse failure is pending - The popover trigger renders as a
<button>witharia-haspopup="dialog",aria-expanded, and a value-awarearia-label prefers-reduced-motion: reducedisables the crosshair-position animation
OKLCH engine
The picker presents OKLCH internally — a perceptually-uniform color space — while reading and writing hex strings to the consumer. Out-of-gamut OKLCH triples (chromas above what sRGB can represent) are rendered dimmed toward neutral grey to signal "this hue/lightness can't be displayed exactly". The math itself is exported from @loworbitstudio/visor-theme-engine, the same engine that powers the docs theme creator.