rc

ColorPicker

A ColorPicker combines a swatch with a customizable popover for editing a color.

installyarn add @react-spectrum/color
version3.0.0-rc.1
usageimport {ColorPicker, ColorEditor} from '@react-spectrum/color'

Example#


<ColorPicker label="Fill" defaultValue="#5100FF">
  <ColorEditor />
</ColorPicker>
<ColorPicker label="Fill" defaultValue="#5100FF">
  <ColorEditor />
</ColorPicker>
<ColorPicker
  label="Fill"
  defaultValue="#5100FF"
>
  <ColorEditor />
</ColorPicker>

Value#


A ColorArea requires either an uncontrolled default value or a controlled value, provided using the defaultValue or value props respectively. The value provided to either of these props should be a color string or Color object.

In the example below, the parseColor function is used to parse the initial color from a HSL string so that value's type remains consistent.

import {ColorPicker} from '@react-spectrum/color';
import {Flex} from '@react-spectrum/layout';
import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] = React.useState(parseColor('hsl(25, 100%, 50%)'));
  return (
    <Flex gap="size-300" wrap>
      <ColorPicker
        label="Color Picker (uncontrolled)"
        defaultValue="hsl(25, 100%, 50%)">        <ColorEditor />
      </ColorPicker>
      <ColorPicker
        label="Color Picker (controlled)"
        value={value}
        onChange={setValue}>        <ColorEditor />
      </ColorPicker>
    </Flex>
  );
}
import {ColorPicker} from '@react-spectrum/color';
import {Flex} from '@react-spectrum/layout';
import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] = React.useState(
    parseColor('hsl(25, 100%, 50%)')
  );
  return (
    <Flex gap="size-300" wrap>
      <ColorPicker
        label="Color Picker (uncontrolled)"
        defaultValue="hsl(25, 100%, 50%)"
      >        <ColorEditor />
      </ColorPicker>
      <ColorPicker
        label="Color Picker (controlled)"
        value={value}
        onChange={setValue}
      >        <ColorEditor />
      </ColorPicker>
    </Flex>
  );
}
import {ColorPicker} from '@react-spectrum/color';
import {Flex} from '@react-spectrum/layout';
import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] =
    React.useState(
      parseColor(
        'hsl(25, 100%, 50%)'
      )
    );
  return (
    <Flex
      gap="size-300"
      wrap
    >
      <ColorPicker
        label="Color Picker (uncontrolled)"
        defaultValue="hsl(25, 100%, 50%)"
      >        <ColorEditor />
      </ColorPicker>
      <ColorPicker
        label="Color Picker (controlled)"
        value={value}
        onChange={setValue}
      >        <ColorEditor />
      </ColorPicker>
    </Flex>
  );
}

Labeling#


A visual label should be provided for the ColorPicker using the label prop.

<ColorPicker label="Stroke color" defaultValue="#345">
  <ColorEditor />
</ColorPicker>
<ColorPicker label="Stroke color" defaultValue="#345">
  <ColorEditor />
</ColorPicker>
<ColorPicker
  label="Stroke color"
  defaultValue="#345"
>
  <ColorEditor />
</ColorPicker>

Accessibility#

If a visible label isn't specified, an aria-label should be provided to the ColorPicker for accessibility. If the field is labeled by a separate element, an aria-labelledby prop must be provided using the id of the labeling element instead.

<ColorPicker aria-label="Fill color" defaultValue="#184">
  <ColorEditor />
</ColorPicker>
<ColorPicker aria-label="Fill color" defaultValue="#184">
  <ColorEditor />
</ColorPicker>
<ColorPicker
  aria-label="Fill color"
  defaultValue="#184"
>
  <ColorEditor />
</ColorPicker>

In addition to the visible or accessibility label, a ColorPicker also announces a description of the current color value (e.g. "dark vibrant blue") as a part of the label.

Internationalization#

For languages that are read right-to-left (e.g. Hebrew and Arabic), the layout of the ColorPicker is automatically flipped.

Events#


ColorPicker accepts an onChange prop which is triggered whenever the value is edited by the user. It receives a Color object as a parameter.

The example below uses onChange to update a separate element with the color value as a string.

import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] = React.useState(parseColor('hsl(50, 100%, 50%)'));

  return (
    <div>
      <ColorPicker
        label="Color"
        value={value}
        onChange={setValue}>
        <ColorEditor />
      </ColorPicker>
      <p>Selected color: {value.toString('hsl')}</p>
    </div>
  );
}
import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] = React.useState(
    parseColor('hsl(50, 100%, 50%)')
  );

  return (
    <div>
      <ColorPicker
        label="Color"
        value={value}
        onChange={setValue}
      >
        <ColorEditor />
      </ColorPicker>
      <p>Selected color: {value.toString('hsl')}</p>
    </div>
  );
}
import {parseColor} from '@react-spectrum/color';

function Example() {
  let [value, setValue] =
    React.useState(
      parseColor(
        'hsl(50, 100%, 50%)'
      )
    );

  return (
    <div>
      <ColorPicker
        label="Color"
        value={value}
        onChange={setValue}
      >
        <ColorEditor />
      </ColorPicker>
      <p>
        Selected color:
        {' '}
        {value.toString(
          'hsl'
        )}
      </p>
    </div>
  );
}

Custom color editor#


ColorEditor provides a default color picker layout including a color area for saturation and brightness, and color sliders for hue and alpha. It also includes ColorFields to view and enter an exact color value by number.

ColorPicker can be customized by providing any combination of color components as children, including ColorArea, ColorField, ColorSlider, ColorSwatchPicker, and ColorWheel.

import {ColorWheel, ColorArea} from '@react-spectrum/color';

<ColorPicker label="Fill" defaultValue="#08f">
  <ColorWheel />
  <ColorArea 
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    size="size-400"
    position="absolute"
    top="calc(50% - size-400)"
    left="calc(50% - size-400)" />
</ColorPicker>
import {ColorWheel, ColorArea} from '@react-spectrum/color';

<ColorPicker label="Fill" defaultValue="#08f">
  <ColorWheel />
  <ColorArea 
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    size="size-400"
    position="absolute"
    top="calc(50% - size-400)"
    left="calc(50% - size-400)" />
</ColorPicker>
import {
  ColorArea,
  ColorWheel
} from '@react-spectrum/color';

<ColorPicker
  label="Fill"
  defaultValue="#08f"
>
  <ColorWheel />
  <ColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    size="size-400"
    position="absolute"
    top="calc(50% - size-400)"
    left="calc(50% - size-400)"
  />
</ColorPicker>

Props#


ColorPicker#

NameTypeDefaultDescription
labelReactNodeA visual label for the color picker.
childrenReactNodeThe contents of the color picker popover, e.g. <ColorEditor />.
size'XS''S''M''L'"M"The size of the color swatch.
rounding'default''none''full'"default"The corner rounding of the color swatch.
valuestringColorThe current value (controlled).
defaultValuestringColorThe default value (uncontrolled).
Events
NameTypeDescription
onChange( (value: Color )) => voidHandler that is called when the value changes.
Accessibility
NameTypeDescription
aria-labelstringDefines a string value that labels the current element.
aria-labelledbystringIdentifies the element (or elements) that labels the current element.
aria-describedbystringIdentifies the element (or elements) that describes the object.
aria-detailsstringIdentifies the element (or elements) that provide a detailed, extended description for the object.

ColorEditor#

NameTypeDescription
hideAlphaChannelbooleanWhether to hide the alpha channel color slider and color field.

Visual options#


Hide alpha channel#

By default, ColorEditor includes a ColorSlider and ColorField for editing the alpha channel. This can be hidden with the hideAlphaChannel prop.

<ColorPicker label="Color" defaultValue="#f80">
  <ColorEditor hideAlphaChannel />
</ColorPicker>
<ColorPicker label="Color" defaultValue="#f80">
  <ColorEditor hideAlphaChannel />
</ColorPicker>
<ColorPicker
  label="Color"
  defaultValue="#f80"
>
  <ColorEditor
    hideAlphaChannel
  />
</ColorPicker>

Swatches#

A ColorEditor can be combined with additional color components such as a ColorSwatchPicker to choose from a list of pre-defined colors.

import {ColorSwatchPicker, ColorSwatch} from '@react-spectrum/color';

<ColorPicker label="Color" defaultValue="#A00">
  <Flex direction="column" gap="size-300">
    <ColorEditor />
    <ColorSwatchPicker>
      <ColorSwatch color="#A00" />
      <ColorSwatch color="#f80" />
      <ColorSwatch color="#080" />
      <ColorSwatch color="#08f" />
      <ColorSwatch color="#088" />
      <ColorSwatch color="#008" />
    </ColorSwatchPicker>
  </Flex>
</ColorPicker>
import {
  ColorSwatch,
  ColorSwatchPicker
} from '@react-spectrum/color';

<ColorPicker label="Color" defaultValue="#A00">
  <Flex direction="column" gap="size-300">
    <ColorEditor />
    <ColorSwatchPicker>
      <ColorSwatch color="#A00" />
      <ColorSwatch color="#f80" />
      <ColorSwatch color="#080" />
      <ColorSwatch color="#08f" />
      <ColorSwatch color="#088" />
      <ColorSwatch color="#008" />
    </ColorSwatchPicker>
  </Flex>
</ColorPicker>
import {
  ColorSwatch,
  ColorSwatchPicker
} from '@react-spectrum/color';

<ColorPicker
  label="Color"
  defaultValue="#A00"
>
  <Flex
    direction="column"
    gap="size-300"
  >
    <ColorEditor />
    <ColorSwatchPicker>
      <ColorSwatch color="#A00" />
      <ColorSwatch color="#f80" />
      <ColorSwatch color="#080" />
      <ColorSwatch color="#08f" />
      <ColorSwatch color="#088" />
      <ColorSwatch color="#008" />
    </ColorSwatchPicker>
  </Flex>
</ColorPicker>

Channel sliders#

This example uses ColorSlider to allow a user to adjust each channel of a color value, with a Picker to switch between color spaces.

import type {ColorSpace} from '@react-spectrum/color';
import {ColorSlider, getColorChannels} from '@react-spectrum/color';
import {Item, Picker} from '@react-spectrum/picker';

function Example() {
  let [space, setSpace] = React.useState<ColorSpace>('rgb');

  return (
    <ColorPicker label="Color" defaultValue="#184">
      <Flex direction="column" gap="size-100">
        <Picker
          aria-label="Color space"
          isQuiet
          selectedKey={space}
          onSelectionChange={(s) => setSpace(s as ColorSpace)}
        >
          <Item key="rgb">RGB</Item>
          <Item key="hsl">HSL</Item>
          <Item key="hsb">HSB</Item>
        </Picker>
        {getColorChannels(space).map((channel) => (
          <ColorSlider key={channel} colorSpace={space} channel={channel} />
        ))}
        <ColorSlider channel="alpha" />
      </Flex>
    </ColorPicker>
  );
}
import type {ColorSpace} from '@react-spectrum/color';
import {
  ColorSlider,
  getColorChannels
} from '@react-spectrum/color';
import {Item, Picker} from '@react-spectrum/picker';

function Example() {
  let [space, setSpace] = React.useState<ColorSpace>('rgb');

  return (
    <ColorPicker label="Color" defaultValue="#184">
      <Flex direction="column" gap="size-100">
        <Picker
          aria-label="Color space"
          isQuiet
          selectedKey={space}
          onSelectionChange={(s) =>
            setSpace(s as ColorSpace)}
        >
          <Item key="rgb">RGB</Item>
          <Item key="hsl">HSL</Item>
          <Item key="hsb">HSB</Item>
        </Picker>
        {getColorChannels(space).map((channel) => (
          <ColorSlider
            key={channel}
            colorSpace={space}
            channel={channel}
          />
        ))}
        <ColorSlider channel="alpha" />
      </Flex>
    </ColorPicker>
  );
}
import type {ColorSpace} from '@react-spectrum/color';
import {
  ColorSlider,
  getColorChannels
} from '@react-spectrum/color';
import {
  Item,
  Picker
} from '@react-spectrum/picker';

function Example() {
  let [space, setSpace] =
    React.useState<
      ColorSpace
    >('rgb');

  return (
    <ColorPicker
      label="Color"
      defaultValue="#184"
    >
      <Flex
        direction="column"
        gap="size-100"
      >
        <Picker
          aria-label="Color space"
          isQuiet
          selectedKey={space}
          onSelectionChange={(s) =>
            setSpace(
              s as ColorSpace
            )}
        >
          <Item key="rgb">
            RGB
          </Item>
          <Item key="hsl">
            HSL
          </Item>
          <Item key="hsb">
            HSB
          </Item>
        </Picker>
        {getColorChannels(
          space
        ).map(
          (channel) => (
            <ColorSlider
              key={channel}
              colorSpace={space}
              channel={channel}
            />
          )
        )}
        <ColorSlider channel="alpha" />
      </Flex>
    </ColorPicker>
  );
}

Rounding#

The rounding of the color swatch can be controlled with the rounding prop.

<Flex direction="column" gap="size-100">
  <ColorPicker label="None" rounding="none" defaultValue="#A00">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Default" rounding="default" defaultValue="#080">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Full" rounding="full" defaultValue="#00F">
    <ColorEditor />
  </ColorPicker>
</Flex>
<Flex direction="column" gap="size-100">
  <ColorPicker
    label="None"
    rounding="none"
    defaultValue="#A00"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Default"
    rounding="default"
    defaultValue="#080"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Full"
    rounding="full"
    defaultValue="#00F"
  >
    <ColorEditor />
  </ColorPicker>
</Flex>
<Flex
  direction="column"
  gap="size-100"
>
  <ColorPicker
    label="None"
    rounding="none"
    defaultValue="#A00"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Default"
    rounding="default"
    defaultValue="#080"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Full"
    rounding="full"
    defaultValue="#00F"
  >
    <ColorEditor />
  </ColorPicker>
</Flex>

Size#

The size of the color swatch can be controlled with the size prop. The default size is "S".

<Flex direction="column" gap="size-100">
  <ColorPicker label="Extra small" size="XS" defaultValue="#A00">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Small" size="S" defaultValue="#080">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Medium" size="M" defaultValue="#FB0">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Large" size="L" defaultValue="#00F">
    <ColorEditor />
  </ColorPicker>
</Flex>
<Flex direction="column" gap="size-100">
  <ColorPicker
    label="Extra small"
    size="XS"
    defaultValue="#A00"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Small" size="S" defaultValue="#080">
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Medium"
    size="M"
    defaultValue="#FB0"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker label="Large" size="L" defaultValue="#00F">
    <ColorEditor />
  </ColorPicker>
</Flex>
<Flex
  direction="column"
  gap="size-100"
>
  <ColorPicker
    label="Extra small"
    size="XS"
    defaultValue="#A00"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Small"
    size="S"
    defaultValue="#080"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Medium"
    size="M"
    defaultValue="#FB0"
  >
    <ColorEditor />
  </ColorPicker>
  <ColorPicker
    label="Large"
    size="L"
    defaultValue="#00F"
  >
    <ColorEditor />
  </ColorPicker>
</Flex>