Primitives
A composable, accessible color picker: a 2D area, channel sliders and hex/channel fields that share one color value.
Note: The color primitives are currently experimental. The API may change in future releases.
Import the color primitives from ng-primitives/color.
import {
Color,
NgpColorPicker,
NgpColorArea,
NgpColorAreaThumb,
NgpColorSlider,
NgpColorSliderTrack,
NgpColorSliderThumb,
NgpColorField,
} from 'ng-primitives/color';
NgpColorPicker is an optional coordinator: it holds a single color value and shares it with any color
components nested inside it. Each color component also works standalone with its own value/valueChange.
<div [(ngpColorPickerValue)]="color" ngpColorPicker>
<!-- adjust two channels on a 2D surface -->
<div ngpColorArea ngpColorAreaXChannel="saturation" ngpColorAreaYChannel="brightness">
<div ngpColorAreaThumb></div>
</div>
<!-- adjust the hue -->
<div ngpColorSlider ngpColorSliderChannel="hue">
<div ngpColorSliderTrack></div>
<div ngpColorSliderThumb></div>
</div>
<!-- edit the hex value -->
<input ngpColorField />
</div>
Color values are represented by an immutable Color object. Parse one from any CSS color string with
Color.parse, and read it back in any format with the to* methods.
import { Color } from 'ng-primitives/color';
const color = Color.parse('#f01e2b'); // hex, rgb(a), hsl(a) and hsb(a) are all supported
color.toHex(); // '#f01e2b'
color.toRgb(); // 'rgb(240, 30, 43)'
color.toHsl(); // 'hsl(356, 88%, 53%)'
color.getRed(); // 240 (or color.getChannelValue('red'))
color.withRed(0); // a new Color, original unchanged
color.withAlpha(0.5).toRgba(); // 'rgba(240, 30, 43, 0.5)'
Reads and derivations auto-convert across spaces, so color.getHue() and color.withHue(200)
(or the generic getChannelValue/withChannelValue) work regardless of the color's current space
(ambiguous channels resolve to hsb).
The value inputs and valueChange outputs are always a Color, so bind [(ngpColorPickerValue)] to a
Color (use Color.parse('#f01e2b') to create one from a string).
The area and sliders compute their functional gradient and expose it as a CSS custom property, which you opt into as a background:
NgpColorArea sets --ngp-color-area-background.NgpColorSlider sets --ngp-color-slider-background (it inherits down to the track).[ngpColorArea] {
background: var(--ngp-color-area-background);
}
[ngpColorSliderTrack] {
background: var(--ngp-color-slider-background);
}
The area background is tuned for the default saturation × brightness pairing. If you set different
xChannel/yChannel values, provide your own background for the area rather than relying on the var.
Here are some additional examples of how to use the color primitives.
A color slider works on its own, without a color picker, adjusting a single channel of its own value.
Set the channel to alpha and layer the gradient over a checkerboard to edit transparency.
Give NgpColorField a channel to edit that channel as a number. Nested in a picker, the fields stay in sync.
NgpColorWheel is a circular alternative to a hue slider. Position the thumb with the --ngp-color-wheel-hue angle.
NgpColorSwatchPicker presents a set of predefined colors as a keyboard-navigable, single-select list.
Pair the picker with a popover so a swatch button opens the full picker on demand.
The following directives are available to import from the ng-primitives/color package:
A circular control adjusting the hue channel. Set its background to var(--ngp-color-wheel-background).
The draggable thumb within a color wheel. Position it with the --ngp-color-wheel-hue custom property.
A non-interactive preview of a color. Set its background to var(--ngp-color-swatch-color).
A single-select list of color swatches with roving-focus keyboard navigation.
A selectable swatch within a swatch picker. Set its background to var(--ngp-color-swatch-color).
Adheres to the Slider WAI-ARIA design pattern.
The area, sliders and wheel each expose a slider role. The color area is a two-dimensional control, so
its thumb additionally exposes an aria-valuetext describing both channels (for example
saturation 50, brightness 70). The swatch picker uses a listbox role with selectable option swatches.
On a slider or the wheel, all four arrows adjust its single channel:
On the color area, the horizontal and vertical arrows adjust separate channels:
For all of the above:
Copyright © 2026 Angular Primitives
This site is powered by Netlify