ColorPicker

Chooses a color, in the formats people work in.

StableSince 1.0.0
On this page

Import

import {
  ColorPicker,
  ColorPickerButton,
  ColorSwatch,
} from '@envsemble/envui/color';

Usage

ColorPicker, ColorPickerButton and ColorSwatch come from their own entry, @envsemble/envui/color, built on React Aria's color hooks, whose libraries the application installs.

  • A ColorPicker takes its label, which names it, a description and an error; visibleLabel={false} hides the label where something else names the picker, such as a popover.
  • value and defaultValue, #000000 by default, take a CSS color string, such as #6750a4, rgb(103, 80, 164) or hsl(256, 34%, 48%), or React Aria's Color.
  • onValueChange receives the color as a string in valueFormat; the picker keeps the hue of a gray itself.
  • valueFormat is hex, the default, #rrggbb or #rrggbbaa while translucent, rgb or hsl.
  • With alpha, the picker adds an alpha slider and field; without it, colors are opaque.
MinimalPicker.tsx
import { useState } from 'react';
import { ColorPicker } from '@envsemble/envui/color';

export default function MinimalPicker() {
  const [color, setColor] = useState('#3b6fd4');
  return (
    // The picker fills its container; a sidebar or a popover gives it its width.
    <div style={{ inlineSize: 'min(100%, 16rem)' }}>
      <ColorPicker label="Accent color" formats={['hex']} value={color} onValueChange={setColor} />
    </div>
  );
}

Formats

Without formats, the picker shows one format at a time, hex first, with the format menu.

  • formats with one format, such as ['hex'], shows it alone, with no menu.
  • With two or more, such as ['hex', 'rgb', 'hsl'], it shows each on a row of its own in that order, with its own copy button.
  • Each row is a group named after its format, so a screen reader says which Red or Alpha it is in.

Offer only the formats and the alpha the stored color can hold: a color stored as #rrggbb takes formats={['hex']} and no alpha, rather than every format and an alpha it would lose.

<ColorPicker label="Brand color" defaultValue="#6b4fa3" formats={['hex', 'rgb', 'hsl']} />
<ColorPicker label="Label color" defaultValue="#2f6f62" formats={['hex']} />

Copy, the eyedropper and swatches

copyable and eyeDropper are on by default. The eyedropper shows only where the browser has one, Chromium-based browsers on the desktop. swatches lists preset colors under the fields: CSS color strings, Colors, or { color, label } with a name.

<ColorPicker
  label="Project color"
  defaultValue="#6b4fa3"
  swatches={[
    { color: '#3b6fd4', label: 'Blue' },
    { color: '#2f6f62', label: 'Teal' },
  ]}
/>

ColorPickerButton

ColorPickerButton takes the picker's props, and opens it in a popover.

  • side places the popover, bottom by default, lined up by align, start by default.
  • defaultOpen starts it open; open and onOpenChange let the application open and close it, such as once a swatch is chosen.
  • size is sm, md or lg, or its container's control height.
  • className, style, ref and the other native props, such as aria-describedby, reach the button.
<ColorPickerButton label="Label color" defaultValue="#2f6f62" />

ColorSwatch

ColorSwatch shows its color, with an optional alpha, and writes it in format, hex, rgb or hsl, after an optional label.

  • Without a format and a label, the sample stands alone, named by the color's description, such as dark purple.
  • size is md, 1 rem and the default, or sm, 0.75 rem, for dense rows; as a Button's icon it takes the icon's size.
  • As the icon of an IconButton in its default variant, the button draws no round fill behind the square sample.
<ColorSwatch color="#6b4fa3" label="Design" format="hex" />

In a form

name submits the color as a string in valueFormat, and form ties it to a form it sits outside; a reset returns to defaultValue.

  • The picker always holds a color, so it takes no required: keep "no color yet" in the form's own state and validate it there.
  • readOnly lets people read and copy the color but not change it.
  • disabled takes no input.
<form onSubmit={apply}>
  <ColorPicker
    label="Project color"
    name="color"
    defaultValue="#6b4fa3"
    formats={['hex', 'rgb']}
    description="Shown beside the project in lists."
  />
  <Button type="submit">Apply color</Button>
</form>

Composition

The picker fills its container up to 18 rem. The picker, env-color-picker, holds its label, env-color-picker-label; the controls, env-color-picker-controls, with the area, env-color-picker-area, and the sliders, env-color-picker-sliders, the hue, env-color-picker-hue, and the alpha, env-color-picker-alpha, each an env-color-picker-slider with its track, env-color-picker-track, and a thumb, env-color-picker-thumb, like the area's; and the values, env-color-picker-values, with the format, env-color-picker-format, the eyedropper, env-color-picker-eye-dropper, copy, env-color-picker-copy, and the fields, env-color-picker-fields, each an env-color-picker-field with its letter, env-color-picker-field-label, and input, env-color-picker-input. Several formats shown together are rows, env-color-picker-row. Then come the swatches, env-color-picker-swatches, each an env-color-picker-swatch, the description, env-color-picker-description, and the error, env-color-picker-error, the shared field error, env-field-error, with its icon. data-channel names a slider's or a field's channel, and data-format a row's format.

ColorPickerButton is env-color-picker-button, with its value, env-color-picker-button-value, and its popover, env-color-picker-popover. ColorSwatch is env-color-swatch, with its sample, env-color-swatch-sample, its label, env-color-swatch-label, and its value, env-color-swatch-value.

Customize

ColorPickerButton has no fill of its own; its container color gives it one.

Its popup is frosted, as every popup is: --env-popup-opacity, --env-popup-blur and --env-popup-shadow, set on a theme, change it, as Popover describes.

Accessibility

You provide

  • A label that names what the color is for.
  • A contrast check where the color carries text, and its message in error.

envUI provides

  • A group named by label, with the area, sliders and fields named after their channels, such as Hue and Alpha, in the EnvUIProvider's language.
  • Value texts that say each channel and the color's name, such as dark vibrant blue.
  • A ColorSwatch alone named by its color's description; beside its value or label, the sample is hidden from assistive technology.

Props

ColorPicker

A compact color picker on React Aria's color hooks: a square saturation and brightness area with a vertical hue slider, and an alpha slider with `alpha`, at its side; under them, a format select, the browser's eyedropper where it has one, a copy button, and fields for the chosen format, or the fields of several `formats` together, each with its own copy button; and preset swatches. Every part works with the keyboard; the channels and the area are named in the EnvUIProvider's language.

PropTypeDescription
visibleLabelDefault true
boolean
The label shows above the picker. false hides it where something else names the picker, such as the popover around it: the label still names the picker for assistive technology.
description
ReactNode
Lasting guidance under the picker, such as where the color shows.
error
ReactNode
A message under the picker that says what is wrong with the color, such as too little contrast.
labelrequired
string
The color's name, such as Accent color; it names the picker, and ColorPickerButton's popover and button.
value
ColorValue
The color in a controlled picker: a CSS color string, such as #6750a4, rgb(103, 80, 164) or hsl(256, 34%, 48%), or React Aria's Color; update it from onValueChange.
defaultValueDefault '#000000'
ColorValue
The color an uncontrolled picker starts at, and that a form reset restores.
onValueChange
(value: string) => void
Receives the color as it changes, as a string in valueFormat, such as #6750a4.
valueFormatDefault 'hex'
'hex''rgb''hsl'
The format of the string onValueChange receives and a form submits: hex (#rrggbb, or #rrggbbaa while translucent), rgb (rgb() or rgba()) or hsl (hsl() or hsla()).
formats
readonly ColorFormat[]
The formats whose fields show together, one under another in this order, such as `['hex', 'rgb', 'hsl']`. With one, the picker shows that format alone; without the prop, it shows one format at a time, hex first, with a select that switches to RGB or HSL.
alphaDefault false
boolean
Whether the color has an alpha: a slider and a field for its opacity, and a value with its alpha while translucent. Without it, colors are opaque.
eyeDropperDefault true
boolean
Whether to show the eyedropper, which picks a color from the screen, where the browser has one (Chromium-based browsers on the desktop); elsewhere it never shows.
copyableDefault true
boolean
Whether to show the button that copies the color, as the fields show it.
swatches
readonly ColorPickerSwatch[]
Preset colors to choose from, under the fields: CSS color strings, React Aria's Colors, or `{ color, label }` with a name, such as the colors of a brand.
name
string
Submits the color with a form under this name, as a string in valueFormat.
form
string
The id of the form the color submits with, where the picker sits outside it.
disabledDefault false
boolean
Whether the picker takes no input, faded.
readOnlyDefault false
boolean
Whether people can read and copy the color, but not change it.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

ColorPickerButton

A compact button that shows a color as a swatch and its value, and opens a ColorPicker in a Popover: the common way to choose a color in a toolbar, a row or a form. The button is named after the label and the color, such as Accent color, #6750A4. className, style, ref and the other native props go to the button.

PropTypeDescription
size
'sm''md''lg'
The button's height, as on every control; without it, its container's.
sideDefault 'bottom'
'top''bottom''left''right''inline-start''inline-end'
The side of the button the picker opens on.
alignDefault 'start'
'start''center''end'
How the picker lines up with the button along that side.
open
boolean
Whether the picker is open, for a picker the application controls with onOpenChange.
defaultOpenDefault false
boolean
Whether an uncontrolled picker starts open, such as in a picture of it.
onOpenChange
(open: boolean, details: PopoverOpenChangeDetails) => void
Receives the requested state, and why, as Popover's onOpenChange does: such as to close the picker once a swatch is chosen.
labelrequired
string
The color's name, such as Accent color; it names the picker, and ColorPickerButton's popover and button.
value
ColorValue
The color in a controlled picker: a CSS color string, such as #6750a4, rgb(103, 80, 164) or hsl(256, 34%, 48%), or React Aria's Color; update it from onValueChange.
defaultValueDefault '#000000'
ColorValue
The color an uncontrolled picker starts at, and that a form reset restores.
onValueChange
(value: string) => void
Receives the color as it changes, as a string in valueFormat, such as #6750a4.
valueFormatDefault 'hex'
'hex''rgb''hsl'
The format of the string onValueChange receives and a form submits: hex (#rrggbb, or #rrggbbaa while translucent), rgb (rgb() or rgba()) or hsl (hsl() or hsla()).
formats
readonly ColorFormat[]
The formats whose fields show together, one under another in this order, such as `['hex', 'rgb', 'hsl']`. With one, the picker shows that format alone; without the prop, it shows one format at a time, hex first, with a select that switches to RGB or HSL.
alphaDefault false
boolean
Whether the color has an alpha: a slider and a field for its opacity, and a value with its alpha while translucent. Without it, colors are opaque.
eyeDropperDefault true
boolean
Whether to show the eyedropper, which picks a color from the screen, where the browser has one (Chromium-based browsers on the desktop); elsewhere it never shows.
copyableDefault true
boolean
Whether to show the button that copies the color, as the fields show it.
swatches
readonly ColorPickerSwatch[]
Preset colors to choose from, under the fields: CSS color strings, React Aria's Colors, or `{ color, label }` with a name, such as the colors of a brand.
name
string
Submits the color with a form under this name, as a string in valueFormat.
form
string
The id of the form the color submits with, where the picker sits outside it.
disabledDefault false
boolean
Whether the picker takes no input, faded.
readOnlyDefault false
boolean
Whether people can read and copy the color, but not change it.

Also accepts the native props of <button>, such as ref, className and aria-* attributes.

ColorSwatch

A small rounded sample of a color, with a hairline edge that keeps light and dark colors visible on every surface and a checkerboard under a translucent one. With `format`, it writes the color's value beside it, and with `label`, a name. Alone, it is an image named by the color's description, such as dark purple, in the EnvUIProvider's language; as a Button's icon it is decorative, and the button's text names the color.

PropTypeDescription
colorrequired
ColorValue
The color it shows: a CSS color string, such as #6750a4, rgb(103, 80, 164) or hsl(256, 34%, 48%), with an optional alpha, or React Aria's Color.
format
'hex''rgb''hsl'
Writes the color beside the sample in this format: hex, such as #6750A4, rgb or hsl. Without it and a label, the sample stands alone, named by the color's description, such as dark purple.
label
ReactNode
A name beside the sample, before the value, such as the label the color belongs to.
sizeDefault 'md'
'sm''md'
The sample's size: sm, 0.75 rem, for dense rows; md, 1 rem, the size of an icon. As a Button's icon it takes the icon's size.

Also accepts the native props of <span>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

ColorPicker

env-color-picker
The color picker.
env-color-picker-alpha
The alpha slider.
env-color-picker-area
The square area of saturation and brightness over the hue.
env-color-picker-controls
The row of the area and the sliders at its side.
env-color-picker-copy
The copy button.
env-color-picker-description
The description under the picker.
env-color-picker-error
The error under the picker.
env-color-picker-eye-dropper
The eyedropper, where the browser has one.
env-color-picker-field
A channel's field with its letter, or the hex field.
env-color-picker-field-label
The letter of a channel's field, such as R.
env-color-picker-fields
The fields of the chosen format, or of one format's row.
env-color-picker-format
The format select.
env-color-picker-hue
The hue slider.
env-color-picker-input
The input of a field.
env-color-picker-label
The label above the picker.
env-color-picker-popover
The popover of a ColorPickerButton, around its picker.
env-color-picker-row
A format's row where several formats show together: its fields and its copy button.
env-color-picker-slider
A slider of one channel.
env-color-picker-sliders
The vertical hue and alpha sliders, side by side.
env-color-picker-swatch
A preset swatch.
env-color-picker-swatches
The preset swatches.
env-color-picker-thumb
The thumb of the area or of a slider.
env-color-picker-track
A slider's track.
env-color-picker-values
The format, the eyedropper and copy, with the fields in equal columns under them.
data-alpha
Present on env-color-picker-values
data-channel
alpha · blue · brightness · green · hex · hue · lightness · red · saturation on env-color-picker-alpha, env-color-picker-field, env-color-picker-hue, env-color-picker-slider
data-disabled
Present on env-color-picker, env-color-picker-alpha, env-color-picker-area, env-color-picker-hue, env-color-picker-slider
data-dragging
Present on env-color-picker-thumb
data-eye-dropper
Present on env-color-picker-values
data-format
hex · hsl · rgb on env-color-picker-row, env-color-picker-values
data-formats
together on env-color-picker-values
data-invalid
Present
data-readonly
Present
data-selected
Present on env-color-picker-swatch
data-translucent
Present on env-color-picker-swatch

ColorPickerButton

env-color-picker-button
The button that shows the color and opens the picker.
env-color-picker-button-value
The color's value on the button.
data-size
lg · md · sm

ColorSwatch

env-color-swatch
A swatch of one color, with its label and value.
env-color-swatch-label
The color's name.
env-color-swatch-sample
The sample of the color.
env-color-swatch-value
The color's value in the format asked for.
data-size
md · sm on env-color-swatch, env-color-swatch-sample
data-translucent
Present on env-color-swatch, env-color-swatch-sample

Color properties

Each sets a color of one instance, through style or CSS; its hover, focus and press follow it. They are public and versioned.

--env-color-picker-button-container
The fill behind the swatch and the value, transparent by default.

Strings

EnvUIProvider's messages overrides each, and a component's own label prop wins over it.

messages.colorPicker.format
"Color format" Names the menu of formats.
messages.colorPicker.formatButton
({ format }) => string Names the button that opens the menu of formats, with the format it shows, such as Hex.
messages.colorPicker.hex
"Hex" The hexadecimal format, in the format select and before its field.
messages.colorPicker.rgb
"RGB" The RGB format, in the format select and before its fields.
messages.colorPicker.hsl
"HSL" The HSL format, in the format select and before its fields.
messages.colorPicker.hexField
"Hex" Names the hexadecimal field.
messages.colorPicker.redShort
"R" The letter beside the red channel's number.
messages.colorPicker.greenShort
"G" The letter beside the green channel's number.
messages.colorPicker.blueShort
"B" The letter beside the blue channel's number.
messages.colorPicker.hueShort
"H" The letter beside the hue's number.
messages.colorPicker.saturationShort
"S" The letter beside the saturation's number.
messages.colorPicker.lightnessShort
"L" The letter beside the lightness's number.
messages.colorPicker.alphaShort
"A" The letter beside the alpha's number.
messages.colorPicker.copy
"Copy color" Names the copy button.
messages.colorPicker.copyFormat
({ format }) => string Names the copy button of one format where several show together, such as Copy color as RGB.
messages.colorPicker.eyeDropper
"Pick a color from the screen" Names the eyedropper button.
messages.colorPicker.swatches
"Swatches" Names the list of preset colors.
messages.colorPicker.button
({ label, value }) => string Names ColorPickerButton after the picker's label and the color, such as Accent, #6750A4.

Changelog

1.0.0

showLabel is visibleLabel, named after the label that visibleLabel={false} hides.

ColorPicker, ColorPickerButton and ColorSwatch come from @envsemble/envui/color, on React Aria's color hooks: hex, RGB and HSL fields named by their letters, with a format menu, an alpha slider and field with alpha, a copy button, the browser's eyedropper and preset swatches. Values are CSS color strings or React Aria's Color, and onValueChange receives both. The area is square with the hue and alpha strips upright at its side, all with square corners, and the fields are quiet. ColorSwatch is a small square that writes its color in a format, with a label and a small size. ColorPickerButton has no fill of its own, as fields have none. Before, the color area and the hue were envUI's own, on Base UI's Slider, with a HEX field.

1.0.0-prerelease.6

Colors under the pointer and while pressed change with --env-motion-ease-enter, rather than easing in slowly, so hover and press show from the first frame.

ColorPickerButton's popover opens over --env-motion-duration-medium, fading in and growing from 98 % with --env-motion-ease-enter, rather than growing from 96 % over the slow duration, so it shows from its first frames rather than late.

The error shows the error icon before its message, as under every field.

1.0.0-prerelease.5

ColorPickerButton takes open and onOpenChange, and passes ref and the native props on to its button.

copy is copyable, as on CodeBlock. onValueChange receives the string alone, without React Aria's Color.

ColorPickerButton's popover is frosted: the popup's color lets a little of what is behind through, blurred, with a soft shadow and no outline edge but a faint hairline in dark, and is solid with its edge at high contrast and with reduced transparency.

1.0.0-prerelease.3

formats with two or more formats shows their fields together, a row each with its own copy button, where in 1.0.0-prerelease.2 it limited the format menu to them; the format menu stays the default. Remove formats to keep the menu, which offers every format. --env-color-picker-button-container gives one ColorPickerButton a fill.