# 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]`.

Source: https://ngwr.dev/reference/components/color-picker  
Kind: Signal Forms, CDK Overlay

## Installation

```angular-ts
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)]`.

```angular-html
<wr-color-picker [(value)]="color" />
```

## 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.

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

## Swatches

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

```angular-html
<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)]`.

```angular-html
<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.

```angular-ts
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.

```angular-html
<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>

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `alpha` | Render the alpha slider and carry alpha in the emitted value — 8-digit hex, or the fourth argument of `rgba()` / `hsla()`. | `boolean` | `true` |
| `format` | Which 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'` |
| `disabled` | Block interaction. | `boolean` | `false` |
| `readonly` | Refuse 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. | `boolean` | `false` |
| `swatches` | Optional 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]

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `value` | Two-way bindable colour string, in whatever `format` names. | `string` | `''` |
| `alpha` | Forwarded to the inner picker. | `boolean` | `true` |
| `format` | Forwarded to the inner picker. | `WrColorFormat` | `'hex'` |
| `swatches` | Forwarded to the inner picker. | `readonly string[]` | `[]` |
| `disabled` | Disable the trigger itself. | `boolean` | `false` |

## [wrColorPickerTrigger] events

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `(opened)` | Fires after the picker overlay opens. | `void` | `—` |
| `(closed)` | Fires after the picker overlay closes. | `void` | `—` |

## Exported utilities

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `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 / hsvToRgb` | RGB ↔ HSV conversions, alpha-preserving. | `function` | `—` |
| `rgbToHsl / hslToRgb` | RGB ↔ 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.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-color-picker-bg` | `var(--wr-color-surface)` | `.wr-color-picker` |
| `--wr-color-picker-border` | `var(--wr-color-outline)` | `.wr-color-picker` |
| `--wr-color-picker-gap` | `0.625rem` | `.wr-color-picker` |
| `--wr-color-picker-hue` | `hsl(0, 100%, 50%)` | `.wr-color-picker` |
| `--wr-color-picker-padding` | `0.75rem` | `.wr-color-picker` |
| `--wr-color-picker-radius` | `var(--wr-border-radius-base)` | `.wr-color-picker` |
| `--wr-color-picker-rgb` | `0, 0, 0` | `.wr-color-picker` |
| `--wr-color-picker-slider-height` | `0.75rem` | `.wr-color-picker` |
| `--wr-color-picker-sv-height` | `10rem` | `.wr-color-picker` |
| `--wr-color-picker-thumb-size` | `0.875rem` | `.wr-color-picker` |
| `--wr-color-picker-width` | `17rem` | `.wr-color-picker` |
| `--wr-preview-size` | `1.75rem` | `.wr-color-picker__preview` |
