Signal FormsCDK Overlay

Color Picker

HSV canvas + hue / alpha sliders + HEX / RGB / HSL inputs + optional swatches. Use <wr-color-picker> inline or anchor it to a button with [wrColorPickerTrigger].

Installation

import { WrColorPicker, WrColorPickerTrigger } from 'ngwr/color-picker';
import { FormsModule } from '@angular/forms';

@Component({
  imports: [WrColorPicker, WrColorPickerTrigger, FormsModule],
})
export class MyComponent {
  protected readonly color = signal('#3969e2');
}

Basic

Drag the canvas, hue strip, alpha strip. Switch HEX / RGB / HSL tabs. Bound through [(value)].

<wr-color-picker [(value)]="color" />
Value: #3969e2

No alpha

Pass [alpha]="false" to hide the alpha slider and drop alpha from the value — 6-digit hex by default, or rgb() / hsl() when format asks for those.

<wr-color-picker [(value)]="color" [alpha]="false" />

Swatches

Pass [swatches] to render a clickable row of preset colours below the inputs.

<wr-color-picker
  [(value)]="color"
  [swatches]="['#3969e2', '#f51c6a', '#00a400', '#ffba00', '#fa383e', '#cbd5e1', '#8594a4', '#0f172a']"
/>

Popover trigger

Apply [wrColorPickerTrigger] to any clickable element. Opens the picker in an anchored overlay; two-way binds through [(value)].

<button wrColorPickerTrigger
        [(value)]="color"
        [swatches]="palette">
  <span class="swatch" [style.background]="color"></span>
  {{ color }}
</button>

Color utilities

Pure functions exported alongside the component. Useful when you need parsing / format conversion without rendering a picker.

import { parseHex, toHex, rgbToHsl } from 'ngwr/color-picker';

const rgb = parseHex('#3969e2');        // { r: 57, g: 105, b: 226, a: 1 }
const hsl = rgbToHsl(rgb!);             // { h: 220, s: 0.74, l: 0.55, a: 1 }
const back = toHex(rgb!, true);         // '#3969e2ff'

Template reference

[wrColorPickerTrigger] exports itself under its own name, so another control can open the swatch panel or read the colour back.

<button type="button" wrColorPickerTrigger [(value)]="brand" #swatch="wrColorPickerTrigger">
  Brand colour
</button>

<!-- Anywhere else in the same template -->
<wr-btn (click)="swatch.open()">Pick a colour</wr-btn>
<span [style.color]="swatch.value()">{{ swatch.value() }}</span>

<wr-color-picker>

NameDescriptionTypeDefault
alphaRender the alpha slider and carry alpha in the emitted value — 8-digit hex, or the fourth argument of rgba() / hsla().booleantrue
formatWhich notation value is written in — hex, rgba or hsla. All three are read on the way IN whichever one is set, so a bound rgb(…) still lands on the canvas; the HEX field always shows canonical hex.WrColorFormat'hex'
disabledBlock interaction.booleanfalse
readonlyRefuse changes while every surface stays focusable and the colour still submits — the sliders keep announcing their value, the numeric fields go natively read-only and the swatches go inert. Switching tabs still works: that changes the notation shown, not the colour.booleanfalse
swatchesOptional row of preset hex colours rendered below the inputs.readonly string[][]
(touch)Emitted on blur, so a bound signal-forms field can mark itself touched.void

[wrColorPickerTrigger]

NameDescriptionTypeDefault
valueTwo-way bindable colour string, in whatever format names.string''
alphaForwarded to the inner picker.booleantrue
formatForwarded to the inner picker.WrColorFormat'hex'
swatchesForwarded to the inner picker.readonly string[][]
disabledDisable the trigger itself.booleanfalse

[wrColorPickerTrigger] events

NameDescriptionTypeDefault
(opened)Fires after the picker overlay opens.void
(closed)Fires after the picker overlay closes.void

Exported utilities

NameDescriptionTypeDefault
parseHex(s)Parse a 3/4/6/8-digit hex string into WrRgb. Returns null on invalid input.(s: string) => WrRgb | null
toHex(rgb, withAlpha?)Format WrRgb as a hex string with leading #.(rgb: WrRgb, withAlpha?: boolean) => string
rgbToHsv / hsvToRgbRGB ↔ HSV conversions, alpha-preserving.function
rgbToHsl / hslToRgbRGB ↔ HSL conversions, alpha-preserving.function

CSS variables

Custom properties ngwr/color-picker publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.

VariableDefaultDeclared on
--wr-color-picker-bgvar(--wr-color-surface).wr-color-picker
--wr-color-picker-bordervar(--wr-color-outline).wr-color-picker
--wr-color-picker-gap0.625rem.wr-color-picker
--wr-color-picker-huehsl(0, 100%, 50%).wr-color-picker
--wr-color-picker-padding0.75rem.wr-color-picker
--wr-color-picker-radiusvar(--wr-border-radius-base).wr-color-picker
--wr-color-picker-rgb0, 0, 0.wr-color-picker
--wr-color-picker-slider-height0.75rem.wr-color-picker
--wr-color-picker-sv-height10rem.wr-color-picker
--wr-color-picker-thumb-size0.875rem.wr-color-picker
--wr-color-picker-width17rem.wr-color-picker
--wr-preview-size1.75rem.wr-color-picker__preview