HyColorPicker
Usage examples on this page are written for Lit / plain HTML (
<hy-color-picker>). The same component ships asHyColorPickerin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A color picker: trigger swatch + popover-hosted HSV selection UI with optional alpha, optional preset swatches, and multi-format readout.
State model
The canonical value is the value prop — a hex string (#RRGGBB, or #RRGGBBAA when alpha is enabled). Internally the component tracks HSV + alpha so that dragging saturation or value to zero does not lose the current hue (a pure RGB round-trip would).
Hex casing — display vs value
Hex is shown uppercase in both readouts (the trigger and the hex field), matching the design-tool convention (Figma, Sketch, Adobe) for digit-heavy color strings. value, the input / change detail, and the form value stay lowercase — the canonical form the CSS / token pipeline emits. Hex is case-insensitive in CSS, so the two never disagree in meaning. Input accepts either case, and the field is left exactly as typed while editing (rewriting mid-keystroke would fight the caret), settling to uppercase on commit. Assert on value case-insensitively.
Interaction
- 2D area: pointer-drag in HSV saturation (x) × value (y). Arrow keys move by 1 / 0.01 steps; Shift increases to 10 / 0.1.
- Hue slider: rainbow track, 0–360°. Arrow keys step by 1° (Shift by 10°).
- Alpha slider (opt-in): transparent → opaque track over a checker background.
- Hex input: accepts short (
#abc), long (#aabbcc), or alpha hex. Commits on Enter / blur. Invalid entries revert. - Swatches: grid of preset colors below the readout. Click applies.
input fires on every interaction (drag, keystroke); change fires on commit (pointer release, Enter, blur, swatch click, popover close with a changed value). Parents that only need the committed value can ignore input.
When to use
- Choosing any color: a brand color, a label color, a theme setting.
- A free choice with a few suggested colors, with
swatches.
Do
- Set
formatto the notation people work with: hex, RGB or HSL.
When not to use
- Only colors from an approved set are valid:
hy-swatch-group. - Tuning one channel such as hue or lightness:
hy-color-slider. - A color that must stay opaque: leave
alphaoff.
Accessibility: your part
- Set
labelto the thing being colored. The default "Color" names nothing. Where the words around it already say so (a row named "Stop 1"), hide the label withlabel=""and name the picker witharia-label/aria-labelledbyon the host; a host name wins overlabel. - When the picked color will sit behind or beside text, show its contrast next to the picker, or limit the choice with
hy-swatch-group.
Examples
Basic
<hy-color-picker value="#3b82f6"></hy-color-picker>With alpha + swatches
<hy-color-picker
value="#3b82f6"
alpha
swatches="#d0021b;#f5a623;#f8e71c;#7ed321;#4a90e2;#bd10e0;#000;#fff"
></hy-color-picker>Helper text, warning and error
<hy-color-picker label="Accent" helper-text="Used for links and focus"></hy-color-picker>
<hy-color-picker
label="Accent"
value="#f8e71c"
warning-message="Low contrast on white"
></hy-color-picker>
<hy-color-picker
label="Accent"
value="#ffffff"
error-message="Pick a color other than white"
></hy-color-picker>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
value | value | string | '#000000' | Current color, as a hex string. Accepts #RGB, #RGBA, #RRGGBB, or #RRGGBBAA, in either case. The component normalizes invalid values back to the previous valid value. |
format | format | 'hex' | 'rgb' | 'hsl' | 'hsv' | 'hex' | Display format for the readout and emitted hsv/rgb/hsl strings. Does NOT change value. |
withoutFormatToggle | without-format-toggle | boolean | false | Hide the format toggle dropdown even when more than one format is useful. |
alpha | alpha | boolean | false | Show the alpha slider and encode alpha in the hex / format readout. |
swatches | swatches | string[] | [] | Preset colors shown in a grid below the readout. Accepts either an array of color strings (property-only) or a ;-separated string (attribute). |
disabled | disabled | boolean | false | Disables all interaction. |
size | size | 'small' | 'medium' | 'large' | 'medium' | Size variant (affects trigger + 2D area). |
label | label | string | 'Color' | Accessible label applied to the trigger and the popover surface. When set, also renders as a visible label above or beside the trigger. |
strings | — | Partial<ColorPickerStrings> | {} | The built-in strings, merged over DEFAULT_COLOR_PICKER_STRINGS — set only the keys you translate. Use for internationalization. |
helperText | helper-text | string | '' | Helper text shown below the trigger. Replaced by the error or warning message while one shows. |
errorMessage | error-message | string | '' | Error message shown below the trigger (replaces the helper text). Setting it raises error. |
error | error | boolean | false | Error state: the color is not accepted and has to change. Paints the trigger border in the danger color and sets aria-invalid. |
warningMessage | warning-message | string | '' | Warning message shown below the trigger (replaces the helper text). Setting it raises warning. |
warning | warning | boolean | false | Warning state: the color is accepted but worth a second look. Paints the warning color and shows warning-message; never sets aria-invalid and never touches form validity. error wins when both are set. |
layout | layout | 'block' | 'inline' | 'block' | Row layout: block (default) stacks label above the trigger; inline puts label on the left and trigger on the right. Helper/error always sits under the trigger (col 2–end), never under the label. Set --hy-color-picker-label-column-width on a wrapping container so stacked pickers align. |
width | width | string | undefined | — | Width of the color-field. Accepts any valid CSS width value (e.g. '400px', '100%', '20rem'). The host fills its container by default; set width to constrain the trigger. Mirrors hy-text-input. |
placement | placement | 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end' | 'bottom-start' | Popover placement — forwarded to hy-popover. |
name | name | string | '' | Form field name. |
open | open | boolean | false | Bound open state of the popover. |
autofocus | autofocus | boolean | false | Marks this color picker as the auto-focus target. Read by hy-dialog (and other overlay containers) on show to choose initial focus. The trigger button receives focus. Also focuses on first connect when used outside an overlay, mirroring native HTML autofocus but routed through JS so SSR'd HTML doesn't pull focus during hydration. |
form | — | HTMLFormElement | null | — | — |
validity | — | ValidityState | — | — |
Events
| Event | Detail | Description |
|---|---|---|
input | — | Fires continuously while the user drags a slider or area. |
change | — | Fires once the value is committed. |
CSS Parts
| Part | Description |
|---|---|
base | Outer wrapper containing label, trigger, and helper/error text |
label | The visible label element |
trigger | The default trigger button |
trigger-swatch | The color swatch inside the trigger |
trigger-readout | The hex readout inside the trigger (uppercase; value stays lowercase) |
surface | The popover surface containing the controls |
area | The 2D saturation × value area |
area-thumb | The thumb inside the 2D area |
slider-hue | The hue slider track |
slider-alpha | The alpha slider track |
readout | The row with hex input + format select |
readout-field | The hex text input (settles to uppercase; accepts either case) |
swatches | The preset swatches grid |
swatch | A single swatch button |
helper-text | Helper text below the trigger |
error-message | Error message below the trigger in the error state |
warning-message | Warning message below the trigger in the warning state |
message-icon | The icon starting the error or warning message |
CSS Custom Properties
The documented hooks. Every override hook the component reads — one per token it paints — is listed in @whitespaceux/harmony/theme-api.json, and @whitespaceux/harmony/component-bindings.json (the Harmony MCP get-bindings tool) says which part and state each one paints.
| Property | Default | Description |
|---|---|---|
--hy-color-picker-icon-size-md | var(--hy-icon-size-md) | Visual swatch edge length inside the trigger. |
--hy-color-picker-icon-size-sm | var(--hy-icon-size-sm) | Visual swatch edge length inside the trigger. |
--hy-color-picker-icon-size-lg | var(--hy-icon-size-lg) | Visual swatch edge length inside the trigger. Independent of the outer trigger height — the swatch sits inside with padding around it. (sm/lg variants follow icon-size-sm/lg) |
--hy-color-picker-radius-form-md | var(--hy-radius-form-md) | Corner radius of the trigger |
--hy-color-picker-radius-overlay-floating-md | var(--hy-radius-overlay-floating-md) | Corner radius of the 2D area |
--hy-color-picker-area-height | — | 2D area height |
--hy-color-picker-area-width | — | 2D area width / minimum surface width |
--hy-color-picker-track-height | — | Slider track height |
--hy-color-picker-thumb-size | — | Thumb diameter |
--hy-color-picker-field-height | — | Hex input / format select height |
--hy-color-picker-gap-form-md | var(--hy-gap-form-md) | Vertical gap between sections |
--hy-color-picker-label-column-width | — | Width of the label column in layout="inline" mode. No default — set on a wrapping container so stacked pickers align. |
--hy-color-picker-control-height-sm | var(--hy-control-height-sm) | Outer trigger height for small size variant. Per-component override in the form-control height contract. |
--hy-color-picker-control-height-md | var(--hy-control-height-md) | Outer trigger height for medium size variant. |
--hy-color-picker-control-height-lg | var(--hy-control-height-lg) | Outer trigger height for large size variant. |
--hy-color-picker-motion-transition-hover-duration | var(--hy-motion-transition-hover-duration) | Transition duration for hover and focus state feedback |
--hy-color-picker-motion-transition-hover-easing | var(--hy-motion-transition-hover-easing) | Transition easing for hover and focus state feedback |
--hy-color-picker-foreground-warning-rest | var(--hy-foreground-warning-rest) | Warning message text and icon color, and the trigger border in the warning state. |
--hy-color-picker-foreground-icon-default-disabled | var(--hy-foreground-icon-default-disabled) | The message line's icon color when the picker is disabled |
--hy-color-picker-gap-layout-2xs | var(--hy-gap-layout-2xs) | Gap between the message icon and its text |
--hy-color-picker-swatch-columns | — | Number of columns in the swatch grid (8 unless set) |