Color Picker
Picks a colour from an area, channel sliders, swatches or the eyedropper.
Usage
import {
ColorPicker,
ColorPickerArea,
ColorPickerAreaThumb,
ColorPickerContent,
ColorPickerControl,
ColorPickerSlider,
ColorPickerTrigger,
ColorPickerValue,
ColorPickerValueSwatch,
} from "@kanzo-tech/ui";<ColorPicker defaultValue="#c97a1e">
<ColorPickerControl>
<ColorPickerTrigger asChild>
<Button variant="outline">
<ColorPickerValueSwatch className="size-4" />
<ColorPickerValue />
</Button>
</ColorPickerTrigger>
</ColorPickerControl>
<ColorPickerContent>
<ColorPickerArea>
<ColorPickerAreaThumb />
</ColorPickerArea>
<ColorPickerSlider channel="hue" />
</ColorPickerContent>
</ColorPicker>value and defaultValue are plain strings here — Ark wants a parsed Color object, and
this wrapper runs parseColor for you. A blank or half-typed string draws the picker with no value
rather than throwing — an empty field and a typo are the ordinary states of a colour input, not
exceptions. parseColor is re-exported if you need one directly, and it throws on anything it
cannot read.
A hidden input is rendered inside the root, so the picker submits with a surrounding form.
Anatomy
Three parts are not in the tree. ColorPickerView is the column that holds the area and the sliders,
and it takes Ark's format — it is how one picker shows an rgba view and an hsla one without
two pickers. ColorPickerSwatchPreview is the round chip of the current colour, sized off the
InputGroup it sits in, and it is pointer-events-none: a preview, never a target. And
ColorPickerTransparencyGrid is the chequerboard that goes behind a swatch so alpha reads as
alpha rather than as a paler colour — ColorPickerSwatchPreview already lays one down, and this is
exported for the swatch you draw yourself.
<ColorPicker>
<ColorPickerControl>
<ColorPickerTrigger />
<ColorPickerEyeDropperTrigger />
<ColorPickerInput channel="hex" />
<ColorPickerContent> ← portalled + positioned for you
<ColorPickerArea>
<ColorPickerAreaThumb />
<ColorPickerSlider channel />
<ColorPickerSwatchGroup>
<ColorPickerSwatchTrigger value>
<ColorPickerSwatch value />
<ColorPickerSwatchIndicator />Swatches and eyedropper
ColorPickerEyeDropperTrigger renders a Button, so it takes variant and size. The
browser's EyeDropper API is not universal — the trigger is a convenience, never the only path
to a colour.
These parts only work inside a picker
ColorPickerSwatch and friends are not a general colour strip, and cannot be borrowed as one:
each calls useColorPickerContext, which is strict and throws outside a root; the
indicator's data-state="checked" is color.isEqual(value) against the single colour the
machine holds; and every trigger is a button announced as select #2e3440 as the color.
Use them when the colour is the value being edited. When it merely pictures a value that
has a name — a palette, a series, a theme — that is Swatch,
which is aria-hidden and never focusable.
API Reference
ColorPicker
| Prop | Type | Default |
|---|---|---|
value | string | — |
defaultValue | string | — |
positioning | PositioningOptions | { placement: "top-start" } |
lazyMount | boolean | true |
unmountOnExit | boolean | true |
ColorPickerArea
| Prop | Type | Default |
|---|---|---|
showDots | boolean | false |
ColorPickerInput
| Prop | Type | Default |
|---|---|---|
channel | ExtendedColorChannel | "hex" |
ColorPickerEyeDropperTrigger
| Prop | Type | Default |
|---|---|---|
variant | ButtonProps["variant"] | "outline" |
size | ButtonProps["size"] | "icon-md" |
useColorPicker re-exports Ark's useColorPickerContext.
ColorPickerProps is exported, so a wrapper can take the same props without restating them.
ColorPickerChangeDetails is Ark's change details plus the one format most consumers actually
store: the machine's format is "rgba" | "hsla" | "hsba" and has no "hex" member, so
valueAsString is never hex and this adds it.