Vize

Color Picker

Accessible, unstyled color picker: 2D area, channel sliders, swatches, text field, and eye dropper.

Package @vizejs/ui/color-picker
Maturity stable
Own the source vize lib pull color-picker
Requires collection, composite-navigation, context, controllable-state, id
Aliases color picker, colour picker, color input, hue slider, eye dropper
Covers HTML input type=color, React Aria ColorPicker, ColorArea, ColorSlider, ColorSwatchPicker, ColorField, Ark UI ColorPicker, EyeDropper API, CSS Color Module Level 4 rgb()/hsl() syntax

Usage

import { ColorPicker, ColorPickerRoot, ColorPickerArea, ColorPickerChannelSlider, ColorPickerEyeDropper, ColorPickerField, ColorPickerSwatch, ColorPickerSwatchGroup } from "@vizejs/ui/color-picker";

Or copy the source into your project with vize lib pull color-picker (see Source Distribution).

API

ColorPicker

Source: src/families/form/color-picker/color-picker-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
modelValue string undefined Controlled color as any CSS color string accepted by parseColor. undefined selects uncontrolled behavior. Unparseable strings keep the last valid color.
defaultValue string "#000000" Initial uncontrolled color, also restored by reset() and native form reset.
format ColorFormat "hex" Serialization used for update:modelValue, slot value, and the form value.
disabled boolean false Remove every part from interaction and sequential focus.
readOnly boolean false Keep parts focusable while rejecting edits.
required boolean false Mark the form value as required (forwarded to the hidden input's data-required).
name string undefined Native form field name. When set, a hidden input submits the formatted value.
form string undefined Id of a form owner outside the root's DOM ancestry.
dir ColorPickerDirection "ltr" Reading direction used for horizontal pointer and arrow-key mapping.
messages ColorPickerMessages undefined Localized accessible strings (channel names, value text, area name). Omitted entries use English defaults.

Events

Event Payload Description
update:modelValue [value: string] Fired with the formatted value whenever the color changes.
change [value: string, detail: ColorPickerChangeDetail] Fired after every distinct color change with the normalized color and its source.
commit [value: string, color: ColorValue] Fired when a continuous interaction (drag end, key press, field commit, pick) settles.

Slots

Slot Slot props Description
default ColorPickerSlotState Compound ColorPicker parts. Receives the current color and availability state.

Exposed

Member Type Description
color —
disabled —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
format —
id —
readOnly —
reset —
setColor —
state —
value —

ColorPickerRoot

Source: src/families/form/color-picker/color-picker-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
modelValue string undefined Controlled color as any CSS color string accepted by parseColor. undefined selects uncontrolled behavior. Unparseable strings keep the last valid color.
defaultValue string "#000000" Initial uncontrolled color, also restored by reset() and native form reset.
format ColorFormat "hex" Serialization used for update:modelValue, slot value, and the form value.
disabled boolean false Remove every part from interaction and sequential focus.
readOnly boolean false Keep parts focusable while rejecting edits.
required boolean false Mark the form value as required (forwarded to the hidden input's data-required).
name string undefined Native form field name. When set, a hidden input submits the formatted value.
form string undefined Id of a form owner outside the root's DOM ancestry.
dir ColorPickerDirection "ltr" Reading direction used for horizontal pointer and arrow-key mapping.
messages ColorPickerMessages undefined Localized accessible strings (channel names, value text, area name). Omitted entries use English defaults.

Events

Event Payload Description
update:modelValue [value: string] Fired with the formatted value whenever the color changes.
change [value: string, detail: ColorPickerChangeDetail] Fired after every distinct color change with the normalized color and its source.
commit [value: string, color: ColorValue] Fired when a continuous interaction (drag end, key press, field commit, pick) settles.

Slots

Slot Slot props Description
default ColorPickerSlotState Compound ColorPicker parts. Receives the current color and availability state.

Exposed

Member Type Description
value string Current value serialized in the root format.
color ColorValue Current normalized color.
format ColorFormat Serialization used for value, the hidden form input, and update:modelValue.
disabled boolean Whether every part suppresses interaction and focus.
readOnly boolean Whether parts stay focusable but reject edits.
state ColorPickerState Stable state token for styling and tests.
element HTMLDivElement | null Rendered root element.
id string Root-owned deterministic base id.
setColor (color: ColorValue | string) => boolean Request a color (object or CSS string) and report whether it changed. Invalid strings are ignored.
reset () => boolean Restore the default value and report whether it changed.

ColorPickerArea

Source: src/families/form/color-picker/color-picker-area.vue

Props

Prop Type Default Description
xChannel ColorChannel "saturation" Channel mapped to the horizontal axis (inline start = minimum).
yChannel ColorChannel "brightness" Channel mapped to the vertical axis (bottom = minimum).
space ColorSpace "hsb" Color space used to resolve hue, saturation, and alpha channels.
ariaLabel string undefined Accessible name of the 2D slider thumb. Defaults to "<X> and <Y>".
ariaLabelledby string undefined Space-separated ids that label the thumb.
ariaDescribedby string undefined Space-separated ids that describe the thumb.

Slots

Slot Slot props Description
default ColorPickerAreaSlotState Thumb contents. Receives both channel values and thumb position.

Exposed

Member Type Description
element HTMLDivElement | null Rendered area element.
thumb HTMLDivElement | null Rendered focusable thumb element.
focus (options?: FocusOptions) => void Move focus to the thumb.

ColorPickerChannelSlider

Source: src/families/form/color-picker/color-picker-channel-slider.vue

Props

Prop Type Default Description
channel (required) ColorChannel required Channel edited by this slider, e.g. "hue" or "alpha".
space ColorSpace "hsb" Color space used to resolve hue, saturation, and alpha.
orientation ColorPickerOrientation "horizontal" Layout axis. Vertical sliders place the minimum at the bottom.
step number undefined Arrow-key and snapping increment. Defaults to the channel's natural step.
ariaLabel string undefined Accessible name. Defaults to the English channel label, e.g. "Hue".
ariaLabelledby string undefined Space-separated ids that label the thumb.
ariaDescribedby string undefined Space-separated ids that describe the thumb.

Slots

Slot Slot props Description
default ColorPickerChannelSliderSlotState Thumb contents. Receives the channel value and thumb position.

Exposed

Member Type Description
element HTMLDivElement | null Rendered track element.
thumb HTMLDivElement | null Rendered focusable thumb element.
value number Current snapped channel value.
focus (options?: FocusOptions) => void Move focus to the thumb.

ColorPickerEyeDropper

Source: src/families/form/color-picker/color-picker-eye-dropper.vue

Props

Prop Type Default Description
unsupported ColorPickerEyeDropperFallback "disable" Rendering when the EyeDropper API is unavailable (and always during SSR): "disable" keeps a disabled button, "hide" adds the hidden attribute.
preserveAlpha boolean true Keep the current alpha; the system picker always returns an opaque color.
ariaLabel string undefined Accessible name when the default slot has no text.

Events

Event Payload Description
pick [color: ColorValue, sRGBHex: string] Fired with the picked color after it has been applied.
cancel [] Fired when the user dismisses the system picker.
error [error: unknown] Fired when the picker rejects for a reason other than dismissal.

Slots

Slot Slot props Description
default ColorPickerEyeDropperSlotState Button contents. Receives support and picking state.

Exposed

Member Type Description
supported boolean Whether the browser provides the EyeDropper API (always false during SSR).
picking boolean Whether the system picker is open.
state ColorPickerEyeDropperState Stable state token for styling and tests.
element HTMLButtonElement | null Rendered native button.
open () => Promise<ColorValue | null> Open the system picker. Resolves with the picked color, or null when cancelled or unsupported.

ColorPickerField

Source: src/families/form/color-picker/color-picker-field.vue

Props

Prop Type Default Description
format ColorFormat undefined Serialization shown in the field. Defaults to the root format.
preserveAlpha boolean false Keep the current alpha when the typed color has no alpha component (for example typing #ff0000 into a half-transparent picker).
ariaLabel string undefined Accessible name when no <label> or aria-labelledby supplies one.
ariaLabelledby string undefined Space-separated ids that label the field.
ariaDescribedby string undefined Space-separated ids that describe the field.
placeholder string undefined Native placeholder text.

Events

Event Payload Description
invalid [draft: string, nativeEvent: Event | null] Fired when a committed draft cannot be parsed and the field reverts.

Exposed

Member Type Description
element HTMLInputElement | null Rendered native text input.
draft string Current draft text.
state ColorPickerFieldState Validity of the draft text.
commit () => boolean Parse and commit the draft; invalid drafts revert. Returns whether it parsed.
revert () => void Discard the draft and show the current color.
focus (options?: FocusOptions) => void Move focus to the input.

ColorPickerSwatch

Source: src/families/form/color-picker/color-picker-swatch.vue

Props

Prop Type Default Description
value (required) string required CSS color selected by this swatch, e.g. "#ff0000" or "hsl(210 80% 40%)".
disabled boolean false Disable this swatch while keeping it visible.
label string undefined Accessible name. Defaults to the color serialized in the root format.
order number undefined Deterministic order for virtualized or portalled swatches.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before selection. Call preventDefault() to keep the current color.

Slots

Slot Slot props Description
default ColorPickerSwatchSlotState Swatch contents, e.g. a check mark. Receives selection state.

Exposed

Member Type Description
value string Swatch color string exactly as supplied.
color ColorValue Parsed swatch color.
checked boolean Whether the swatch matches the root color.
disabled boolean Whether the swatch or root suppresses selection.
state ColorPickerSwatchState Stable state token for styling and tests.
element HTMLDivElement | null Rendered swatch element.
focus (options?: FocusOptions) => void Move focus to the swatch.

ColorPickerSwatchGroup

Source: src/families/form/color-picker/color-picker-swatch-group.vue

Props

Prop Type Default Description
loop boolean true Whether arrow-key navigation wraps at the first and last enabled swatch.
ariaLabel string undefined Accessible name of the radiogroup, e.g. "Saved colors".
ariaLabelledby string undefined Space-separated ids that label the radiogroup.
ariaDescribedby string undefined Space-separated ids that describe the radiogroup.

Slots

Slot Slot props Description
default ColorPickerSlotState ColorPickerSwatch children. Receives the root color state.

Exposed

Member Type Description
element HTMLDivElement | null Rendered radiogroup element.
focus (options?: FocusOptions) => void Move focus to the checked, active, or first enabled swatch.

Behavior

Normative state x input -> outcome table for color-picker-root.vue, color-picker-area.vue, color-picker-channel-slider.vue, color-picker-swatch-group.vue, color-picker-swatch.vue, color-picker-field.vue, and color-picker-eye-dropper.vue (@vizejs/ui/color-picker), plus the pure color model in color-picker-color.ts. Every row is proven by the named test.

Value model

v-model is a CSS color string. Any syntax accepted by parseColor may be supplied (#rgb[a], #rrggbb[aa], rgb()/rgba() and hsl()/hsla() in legacy comma or CSS Color 4 space/slash syntax, hue units deg/grad/rad/ turn, the non-CSS hsb(), and transparent); emitted values are serialized in the root format (hex by default, which becomes #rrggbbaa below full opacity). Internally the root keeps the last accepted color as an immutable HSB ColorValue, so hue survives greys and saturation survives black while a user drags. The typed ColorValue is available through change details, slot state, and setColor. Unparseable model strings keep the last valid color.

Table

ID State Input Outcome Evidence
CP1 model parse hex 3/4/6/8-digit hex parses case-insensitively; malformed hex returns null parses every hex notation and normalizes to lowercase
CP2 model parse rgb legacy and modern rgb, percentages, and alpha parse; channels clamp like CSS; malformed argument lists return null parses legacy and modern rgb syntax with percentages and alpha
CP3 model parse hsl / hsb hue units deg/grad/rad/turn and negative hues wrap; hsb notation parses; bad units return null parses hsl with angle units and hsb notation
CP4 model parse keyword / empty transparent parses; empty and unsupported named colors return null parses transparent and rejects empty or unknown input
CP5 model format every ColorFormat serializes with and without alpha; hex is the default formats every color format with and without alpha
CP6 model round-trip 8-bit colors round-trip losslessly through hex, hex8, rgb, and hsb round-trips every 8-bit primary and secondary through each format
CP7 model convert hsb ↔ rgb ↔ hsl conversions are exact converts between hsb, rgb, and hsl exactly
CP8 model achromatic convert greys keep the fallback hue; black keeps the fallback saturation achromatic conversions keep the fallback hue and saturation
CP9 model create hue wraps, channels clamp, non-finite channels fall back, results are frozen createColor wraps hue and clamps every channel
CP10 model channel get/set every channel reads and writes in its space; out-of-range values clamp reads and writes every channel in its color space
CP11 model channel metadata space resolution, ranges, labels, snapping, and aria-valuetext strings are stable resolves channel spaces, ranges, labels, snapping, and value text
CP12 model gradient channel track gradients interpolate exactly (hue uses six segments, lightness three stops) builds exact channel preview gradients
CP13 model equality / guards equality is 8-bit sRGB plus 1/255 alpha; isColorValue / isColorFormat narrow unknown input compares colors at 8-bit precision and guards unknown values
CP14 helpers pointer / keys / platform pointer fractions clamp and flip in RTL; key intents cover arrows, Shift, Page keys, Home/End; capture and EyeDropper helpers tolerate missing APIs; swatch ids are DOM-safe maps pointer coordinates to clamped fractions in both directions, maps fractions and values across channel ranges, resolves one- and two-dimensional keyboard intents, pointer capture helpers tolerate missing or throwing platform APIs, eye dropper helpers feature-detect and validate untyped platform values, creates DOM-id-safe swatch segments for arbitrary color strings
CP15 root default render role="group" root exposes id, data-state/value, --vize-ui-color-picker-* custom properties, slot state, and a hidden form input renders a labelled root with color custom properties, slot state, and form value
CP16 area pointer down / move / up pointer position maps to saturation (x) and brightness (y, bottom = 0), focuses the thumb, publishes thumb vars, commits on release area maps pointer drags to saturation and brightness with a committed release
CP17 area Arrow / Shift+Arrow / Page / Home / End one role="slider" thumb with aria-roledescription="2D slider" and combined aria-valuetext; each key edits one axis and commits area thumb exposes 2D slider semantics and keyboard steps
CP18 area, custom axes keys through grey hue survives achromatic intermediates; any channel pair (e.g. hue × lightness) can drive the area area keeps the hue while dragging through greys and supports custom channels
CP19 channel slider keys / pointer hue, alpha (vertical), and rgb channels step, page, jump, and follow pointer position; track gradient and percent vars update channel sliders edit hue, alpha, and rgb channels with keyboard and pointer
CP20 dir="rtl" ArrowRight / pointer horizontal arrows and pointer mapping invert right-to-left layouts invert horizontal arrows and pointer mapping
CP21 swatch group Tab / Arrow / click / Space radiogroup of radio swatches with roving tabindex; arrows move and select skipping disabled swatches; click and Space select swatches form a roving radiogroup that selects on click and arrow keys
CP22 swatch click with preventDefault() selection is cancelled swatch click can be cancelled before selection
CP23 field type / Enter / blur / Escape / commit() drafts validate live (aria-invalid), Enter and blur commit parseable text, invalid commits emit invalid and revert, Escape reverts field parses on Enter and blur, flags invalid drafts, and reverts them
CP24 field preserveAlpha commit opaque text the current alpha is kept and the field can use its own format field can preserve the current alpha and follow its own format
CP25 controlled edit emits the requested value while rendering the controlled color until the parent accepts it; invalid model keeps the last color controlled value wins until the parent accepts the request
CP26 disabled / read-only keys / pointer / Tab disabled removes thumbs from the tab order and disables inputs; read-only stays focusable, marks aria-readonly, rejects edits disabled and read-only roots suppress edits while read-only stays focusable
CP27 exposed root setColor / reset exposes value, color, format, state, element; setColor accepts strings or ColorValue and rejects invalid strings exposes typed state and imperative setColor/reset controls
CP28 inside <form> native reset uncontrolled roots restore defaultValue and the submitted value native form reset restores the default value
CP29 eye dropper supported click / open() opens the system picker, applies the sRGB result (keeping alpha by default), emits pick; AbortError emits cancel, others error eye dropper feature-detects, picks, preserves alpha, and reports cancel
CP30 eye dropper unsupported render data-state="unsupported"; unsupported="disable" disables, "hide" adds hidden eye dropper disables or hides itself without platform support
CP31 missing provider setup parts fail closed with the shared context diagnostic compound parts require a matching root provider
CP32 SSR and hydration render twice / hydrate markup is byte-identical per request (eye dropper renders unsupported on the server) and hydrates without warnings or id changes renders byte-identical color picker markup across isolated SSR requests, hydrates generated color picker ids without changing the server contract
CP33 messages render channel names, aria-valuetext, and the 2D area name come from the typed messages prop; omitted entries use English defaults messages localize channel names, value text, and the area name

Notes

  • Area keyboard map: Left/Right edit the x channel, Up/Down the y channel, Shift multiplies to the channel page step, Page Up/Down page the y channel, Home/End jump the x channel. Horizontal keys invert under dir="rtl".
  • Default accessible names are English ("Hue", "Saturation and Brightness"); pass ariaLabel/ariaLabelledby to localize.
  • commit fires once per settled interaction (pointer release, each key press, field commit, swatch selection, eye-dropper pick); change fires for every intermediate color.
  • No CSS ships. Style from data-* hooks and the published custom properties: --vize-ui-color-picker-color, -opaque-color, -hue, -alpha (root), -thumb-x, -thumb-y, -area-hue, -area-background (area), -thumb-percent, -track-background (slider), -swatch-color (swatch).