ColorPicker
betav0.1.0A single colour field with a popover panel: an editable hex trigger with an inline swatch, and a panel offering a saturation/brightness area, hue slider, optional alpha slider, an eyedropper, a format selector (HEX/RGB/HSL/HSB), value inputs, and an optional preset-swatch grid. Vendored from DiceUI's radix-base colour picker and re-tokenized to FDS; output is a hex string by default.
Variants
Examples
<ColorPicker label="Label color" defaultValue="#009EDB" onValueChange={setColor} /><ColorPicker
label="Theme background"
value={color}
onValueChange={setColor}
helperText="Applies to the product navigation bar"
/><ColorPicker label="Accent" alpha value={rgba} onValueChange={setRgba} /><ColorPicker label="Brand" showSwatches value={color} onValueChange={setColor} /><ColorPicker label="Status" error="Pick a color" required onValueChange={setColor} />Props
| Prop | Type |
|---|---|
value | string — Controlled colour value. Hex by default (#RRGGBB); #RRGGBBAA when alpha is enabled |
defaultValue | string — Uncontrolled initial value |
onValueChange | (value: string) => void — Fired on every colour change; emits a hex string (#RRGGBBAA when alpha is on) for a resolved colour, "" when cleared, or a non-parsing hex-field draft (e.g. "red") verbatim so a controlled parent never holds a stale value |
label | ReactNode — Field label. Omit → aria-label or aria-labelledby required (RULE-01) |
infoTooltip | ReactNode — Info affordance rendered next to the label (caller-owned) |
helperText | ReactNode — Help text under the field |
error | string — Error message. String only (no boolean) — presence toggles the error visual and replaces helperText (RULE-04) |
required | boolean — Renders the `*` marker (when a label is present) and sets aria-required |
disabled | boolean — Disables the trigger and the whole panel (RULE-06) |
placeholder | string — Placeholder shown in the empty trigger. Defaults to "Select color" |
alpha | boolean — Enables the alpha slider + opacity input. Off by default; enabling it changes the output shape to #RRGGBBAA (RULE-03) |
formats | ColorFormat[] — Formats offered in the panel selector. Defaults to ["hex","rgb","hsl","hsb"] |
format | ColorFormat — Initial/controlled panel format. Defaults to "hex" |
showSwatches | boolean — Shows the preset-swatch grid. Off by default (RULE-07) |
presets | readonly string[] — Preset colours. Defaults to the official Filigran palette (DEFAULT_PRESETS) |
eyeDropper | boolean — Shows the eyedropper button, auto-hidden where unsupported. Defaults to true (RULE-08) |
name | string — Form field name for the hidden input |
className | string — Additional CSS classes on the outer wrapper (RULE-12) |
Accessibility
Trigger is an editable hex <input> paired with a palette IconButton that opens a Radix Popover (aria-expanded, aria-haspopup) — the hex value is keyboard-editable in BOTH the trigger and the panel's value input (RULE-09). The area is a role="slider" 2D control with an aria-valuetext of the current saturation/brightness and arrow-key stepping (Shift = ×10) for WCAG 2.1.1. The hue and alpha sliders are the vendored colour sliders (gradient track), not the FDS Slider (RULE-10); they inherit role=slider + aria-valuemin/max/now from @radix-ui/react-slider and align their thumb tokens (--icon-default) to the FDS Slider for family consistency. Each value input is a labelled <input> (per-channel aria-labels); preset swatches are labelled buttons with aria-pressed. Colour is never signalled by chroma alone — the hex/channel text always states the value (WCAG 1.4.1). The eyedropper is a best-effort FDS IconButton, auto-hidden where window.EyeDropper is unsupported (Firefox/Safari) — the panel reads correctly without it (RULE-08). An unlabeled field warns in development (console.warn, never a throw), matching Input. The field's disabled tones are contrast-exempt as an inactive component (WCAG 1.4.3 Note 1): the trigger input's bg/text come from `disabled:` variants, while the label, required marker and helper text switch to text-input-disabled through explicit tone selection — both apply only when the whole field is disabled; the three intrinsic gradients (hue rainbow, area saturation/brightness, alpha checkerboard) are decorative and carry no text, so they are not contrast pairs (RFC §3.4). Focus uses the standard FDS ring (ring-focus + ring-offset-focus) on every interactive element.