Color Picker

A composable color picker component supporting multiple color models, alpha channel, and customizable UI.

1<ColorPicker
2 defaultValue="#DA2929"
3 style={{
4 width: "240px",
5 height: "320px",
6 padding: 12,
7 background: "white",
8 }}
9>
10 <ColorPicker.Area />
11 <ColorPicker.Hue />
12 <ColorPicker.Alpha />
13 <Flex direction="row" gap={2}>
14 <ColorPicker.Mode />
15 <ColorPicker.Input copyable />

Anatomy

Import and assemble the component:

1import { ColorPicker } from '@raystack/apsara'
2
3<ColorPicker>
4 <ColorPicker.Area />
5 <ColorPicker.Hue />
6 <ColorPicker.Alpha />
7 <ColorPicker.Mode />
8 <ColorPicker.Input copyable />
9</ColorPicker>

Usage

The picker is composed from an area pad, sliders and an input, so you can drop in the whole thing or keep only the parts you need.

Basic usage

An uncontrolled picker. Pass defaultValue for the starting color and read changes from onValueChange.

1<ColorPicker
2 defaultValue="#00bcd4"
3 style={{
4 width: "240px",
5 height: "220px",
6 padding: 12,
7 background: "white",
8 }}
9>
10 <ColorPicker.Area />
11 <ColorPicker.Hue />
12</ColorPicker>

Copy to clipboard

Pass the copyable prop on ColorPicker.Input to render a copy-to-clipboard button in the input's trailing slot. The button copies the formatted color string in the active mode (e.g. #FF0000, rgb(...), or oklch(...)) and shows a brief confirmation icon after a successful copy.

1<ColorPicker
2 defaultValue="#5B8DEF"
3 style={{
4 width: "240px",
5 height: "300px",
6 padding: 12,
7 background: "white",
8 }}
9>
10 <ColorPicker.Area />
11 <ColorPicker.Hue />
12 <Flex direction="row" gap={2}>
13 <ColorPicker.Mode />
14 <ColorPicker.Input copyable />
15 </Flex>

OKLCH mode

The picker stores color internally in OKLCH. What the controls show depends on the mode:

  • hex, rgb, hsl — the area pad is the familiar HSL saturation × brightness square and the hue slider runs in HSL hue. The picker behaves like a traditional color picker and only emits colors the chosen format can represent.
  • oklch — the pad becomes a chroma × lightness plane covering the full P3 gamut, and the hue slider runs in OKLCH hue, where equal steps are equal perceptual changes.

To start in OKLCH, pass an oklch(...) string as defaultValue and set defaultMode='oklch'.

1<ColorPicker
2 defaultValue="oklch(0.5438 0.191 267.01)"
3 defaultMode="oklch"
4 style={{
5 width: "240px",
6 height: "320px",
7 padding: 12,
8 background: "white",
9 }}
10>
11 <ColorPicker.Area />
12 <ColorPicker.Hue />
13 <ColorPicker.Alpha />
14 <Flex direction="row" gap={2}>
15 <ColorPicker.Mode />

Popover integration

The ColorPicker can be embedded within a Popover component to create a more interactive and space-efficient color selection experience.

1(function PopoverColorPicker() {
2 const [color, setColor] = useState("#DA2929");
3
4 return (
5 <Popover>
6 <Popover.Trigger
7 render={
8 <Button
9 style={{
10 width: 60,
11 height: 60,
12 background: color,
13 }}
14 />
15 }

API Reference

A root holding the pad and sliders, plus formatColor for turning a value into a string yourself.

Root

The ColorPicker is composed of several subcomponents, each responsible for a specific aspect of color selection. The root component acts as a data provider for its children.

Prop

Type

Area

Enables users to select a color from a 2D palette. The surface adapts to the active mode: in hex, rgb, and hsl modes it renders the classic saturation × brightness gradient square; in oklch mode it renders a chroma × lightness plane covering the full P3 gamut.

Hue

Provides a slider for selecting the hue value of the color.

Alpha

Provides a slider for selecting the alpha value of the color.

Mode

Lets users switch between different color models (HEX, RGB, HSL, OKLCH) via a dropdown menu.

Prop

Type

Input

Displays the current color value in the selected color model as a read-only string. The value is updated automatically as the user interacts with the area, hue, or alpha controls. Pass copyable to render a copy-to-clipboard button in the input's trailing slot.

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
color-pickerThe root container (Flex column)
color-picker-areaThe 2D color area (saturation/lightness or chroma/lightness plane)
color-picker-area-canvasThe <canvas> painting the color plane (when in oklch mode)
color-picker-area-thumbThe draggable thumb in the color area
color-picker-hueThe hue slider root
color-picker-alphaThe alpha slider root
color-picker-alpha-gradientThe gradient overlay <div> behind the alpha track
color-picker-slider-controlThe slider control (shared by hue and alpha)
color-picker-slider-trackThe slider track (shared by hue and alpha)
color-picker-slider-rangeThe filled range indicator inside the track (shared by hue and alpha)
color-picker-slider-thumbThe slider thumb (shared by hue and alpha)
color-picker-inputThe read-only color value input
color-picker-modeThe mode select trigger
color-picker-mode-contentThe mode select dropdown content (when open)

formatColor

Converts any CSS color string to the requested format. Useful when consuming apsara color tokens (which are authored in OKLCH) from APIs that need a specific format — chart libraries, SVG attributes, canvas fills, design exports, and similar.

1import { formatColor } from '@raystack/apsara'
2
3formatColor('oklch(0.5438 0.191 267.01)', 'hex') // '#3E63DD'
4formatColor('oklch(0.7 0.32 30)', 'hex') // '#FF5843' (gamut-mapped)
5formatColor('red', 'rgb') // 'rgb(255, 0, 0)'
6formatColor('rgba(255, 0, 0, 0.5)', 'hsl') // 'hsla(0, 100%, 50%, 0.5)'
7formatColor('#FF0000', 'oklch') // 'oklch(0.6279 0.2577 29.23)'
8formatColor('not a color', 'hex') // null

Behavior

  • Accepts any CSS color string: oklch(), rgb()/rgba(), hsl()/hsla(), hex, named colors, transparent.
  • For hex, rgb, and hsl outputs, wide-gamut OKLCH inputs are gamut-mapped into sRGB by reducing chroma while preserving lightness and hue, so the returned string is the closest sRGB representation rather than a per-channel-clipped one (which would distort hue).
  • For oklch output, the full color is preserved — OKLCH can express the wide gamut natively. Output matches the design system's token format (4-decimal L/C, 2-decimal H, hue pinned to 0 when achromatic).
  • Hex is uppercase; uses 8-digit form (#rrggbbaa) when alpha < 1. Translucent rgb/hsl/oklch produce rgba() / hsla() / oklch(... / A).
  • Returns null for unparseable input rather than throwing — safe to call on user-supplied strings.

Signature

1function formatColor(
2 value: string,
3 format: 'hex' | 'rgb' | 'hsl' | 'oklch'
4): string | null

Accessibility

  • Provides aria-label attributes for color areas and sliders
  • Supports keyboard navigation for hue, saturation, and alpha controls
  • Color values are announced to screen readers on change