GitHub

Color Picker

Form-associated color picker — native color input, hex text field, and an optional swatch grid. A Lit Web Component migrated from the Angular esa-color-picker.

Stable wc import '@esa/ecology/esa-color-picker';

Preview

<esa-color-picker label="Brand color" value="#43608a"></esa-color-picker>

Swatches

Pass preset colors as a JSON-encoded swatches attribute (or a string[] property). The selected swatch is highlighted.

<esa-color-picker label="Pick a brand color" value="#43608a" swatches='["#43608a","#5787b9","#f9a134","#ef4444","#3b82f6","#22c55e"]'></esa-color-picker>

Sizes

<esa-color-picker label="Extra small" size="xs" value="#43608a"></esa-color-picker>
<esa-color-picker label="Small" size="sm" value="#5787b9"></esa-color-picker>
<esa-color-picker label="Medium" size="md" value="#f9a134"></esa-color-picker>
<esa-color-picker label="Large" size="lg" value="#ef4444"></esa-color-picker>

States

Hide the hex input with show-input={false}; disable the whole control with disabled.

<esa-color-picker label="No hex input" value="#3b82f6" show-input="false" swatches=""></esa-color-picker>
<esa-color-picker label="Disabled" value="#22c55e" disabled swatches=""></esa-color-picker>

API

PropTypeDefaultDescription
label string '' Field label above the control.
value string '#000000' Current color as a hex string.
size 'xs' | 'sm' | 'md' | 'lg' 'md' Control size (reflected attribute).
swatches string[] [] Preset colors. Accepts a string[] property or a JSON-encoded swatches attribute.
show-input boolean true Show the hex text input next to the preview.
disabled boolean false Disables interaction (reflected attribute).

Events

EventTypeDefaultDescription
change CustomEvent<{ value: string }> Fired when the color commits (native picker, valid hex input, or swatch click). Hex input validates #rgb / #rrggbb. Composed and bubbles.

Accessibility

  • The native <input type="color"> provides the OS color dialog and keyboard handling.
  • Swatches are a role="listbox" group; each swatch is role="option" with aria-selected and an aria-label ("Select color {hex}").
  • Hex input only commits valid #rgb / #rrggbb values, preventing invalid form state.
  • Form-associated via ElementInternals — value submits with the enclosing form.

Theming surface

Every public token this component reads, extracted from its source at build time. The Resolves to column walks each token's real lineage — component → semantic → primitive → raw value — so you can see exactly where re-pointing it lands. A spoke re-skins by overriding these in its theme-<slug>.css; component internals are never edited. No hook for what you need? File it with /request-lego.

TokenTierResolves to
--focus-ring-color component #65ba74 via --color-border-focus--color-grass-8
--focus-ring-width component 2px
--form-bg component #fcfcfc via --color-surface--color-gray-1
--form-bg-disabled component #f0f0f0 via --color-disabled-bg--color-gray-3
--form-border-color component #cecece via --color-border--color-gray-7
--form-border-color-focus component #65ba74 via --color-border-focus--color-grass-8
--form-border-width component 1px
--form-font-size-lg component clamp(0.875rem, 0.77rem + 0.52vw, 1.125rem) via --type-size-300
--form-font-size-md component clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --type-size-200
--form-font-size-sm component clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --type-size-100
--form-font-size-xs component clamp(0.5rem, 0.44rem + 0.3vw, 0.625rem) via --type-size-050
--form-height-lg component 48px
--form-height-md component 40px
--form-height-sm component 32px
--form-height-xs component 28px
--form-padding-x-lg component 1rem via --spacing-400
--form-padding-x-md component 0.75rem via --spacing-300
--form-padding-x-sm component 0.625rem via --spacing-250
--form-padding-x-xs component 0.5rem via --spacing-200
--form-radius-lg component 0.5rem via --radius-200
--form-radius-md component 0.5rem via --radius-200
--form-radius-sm component 0.25rem via --radius-100
--form-radius-xs component 0.25rem via --radius-100
--form-text-color component #202020 via --color-text-primary--color-gray-12
--color-primary semantic #46a758 via --color-grass-9
--color-text-primary semantic #202020 via --color-gray-12
--font-mono semantic 'DM Mono', monospace
--font-sans semantic 'DM Sans', sans-serif
--transition-fast semantic 150ms ease
--font-weight-medium primitive 500
--radius-050 primitive 0.125rem
--spacing-100 primitive 0.25rem
--spacing-200 primitive 0.5rem
--spacing-300 primitive 0.75rem