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.
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>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 normalises 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. |
helpText | help-text | string | '' | Helper text shown below the trigger. Hidden when errorMessage is shown. |
errorMessage | error-message | string | '' | Error message shown below the trigger when invalid. |
invalid | invalid | boolean | false | Visually marks the control as invalid. |
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 when invalid |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-color-picker-swatch-size | Visual swatch edge length inside the trigger. Independent of the outer trigger height — the swatch sits inside with padding around it. Default: var(--hy-icon-size-md) (sm/lg variants follow icon-size-sm/lg) |
--hy-color-picker-trigger-radius | Corner radius of the trigger |
--hy-color-picker-surface-radius | 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 | 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-height-sm | Outer trigger height for small size variant. Per-component override in the form-control height contract (see .claude/rules/control-heights.md). Default: var(--hy-control-height-sm) |
--hy-color-picker-height-md | Outer trigger height for medium size variant. Default: var(--hy-control-height-md) |
--hy-color-picker-height-lg | Outer trigger height for large size variant. Default: var(--hy-control-height-lg) |
--hy-color-picker-hover-duration | Transition duration for hover and focus state feedback |
--hy-color-picker-hover-easing | Transition easing for hover and focus state feedback |