beta

ColorPicker

A ColorPicker synchronizes a color value between multiple React Aria color components. It simplifies building color pickers with customizable layouts via composition.

installyarn add react-aria-components
version1.2.0
usageimport {ColorPicker} from 'react-aria-components'

Example#


import {Button, ColorPicker, Dialog, DialogTrigger, Popover} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorSlider} from './ColorSlider';
import {MyColorArea} from './ColorArea';
import {MyColorField} from './ColorField';

<ColorPicker defaultValue="#5100FF">
  <DialogTrigger>
    <Button className="color-picker">
      <MyColorSwatch />
      <span>Fill color</span>
    </Button>
    <Popover placement="bottom start">
      <Dialog className="color-picker-dialog">
        <MyColorArea
          colorSpace="hsb"
          xChannel="saturation"
          yChannel="brightness"
        />
        <MyColorSlider colorSpace="hsb" channel="hue" />
        <MyColorField label="Hex" />
      </Dialog>
    </Popover>
  </DialogTrigger>
</ColorPicker>
import {
  Button,
  ColorPicker,
  Dialog,
  DialogTrigger,
  Popover
} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorSlider} from './ColorSlider';
import {MyColorArea} from './ColorArea';
import {MyColorField} from './ColorField';

<ColorPicker defaultValue="#5100FF">
  <DialogTrigger>
    <Button className="color-picker">
      <MyColorSwatch />
      <span>Fill color</span>
    </Button>
    <Popover placement="bottom start">
      <Dialog className="color-picker-dialog">
        <MyColorArea
          colorSpace="hsb"
          xChannel="saturation"
          yChannel="brightness"
        />
        <MyColorSlider colorSpace="hsb" channel="hue" />
        <MyColorField label="Hex" />
      </Dialog>
    </Popover>
  </DialogTrigger>
</ColorPicker>
import {
  Button,
  ColorPicker,
  Dialog,
  DialogTrigger,
  Popover
} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorSlider} from './ColorSlider';
import {MyColorArea} from './ColorArea';
import {MyColorField} from './ColorField';

<ColorPicker defaultValue="#5100FF">
  <DialogTrigger>
    <Button className="color-picker">
      <MyColorSwatch />
      <span>
        Fill color
      </span>
    </Button>
    <Popover placement="bottom start">
      <Dialog className="color-picker-dialog">
        <MyColorArea
          colorSpace="hsb"
          xChannel="saturation"
          yChannel="brightness"
        />
        <MyColorSlider
          colorSpace="hsb"
          channel="hue"
        />
        <MyColorField label="Hex" />
      </Dialog>
    </Popover>
  </DialogTrigger>
</ColorPicker>
Show CSS
@import "@react-aria/example-theme";

.color-picker {
  background: none;
  border: none;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  outline: none;
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1rem;
  color: var(--text-color);

  &[data-focus-visible] {
    outline: 2px solid var(--focus-ring-color);
    outline-offset: 2px;
  }
}

.color-picker-dialog {
  outline: none;
  padding: 15px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 192px;
  max-height: inherit;
  box-sizing: border-box;
  overflow: auto;
}
@import "@react-aria/example-theme";

.color-picker {
  background: none;
  border: none;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  outline: none;
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1rem;
  color: var(--text-color);

  &[data-focus-visible] {
    outline: 2px solid var(--focus-ring-color);
    outline-offset: 2px;
  }
}

.color-picker-dialog {
  outline: none;
  padding: 15px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 192px;
  max-height: inherit;
  box-sizing: border-box;
  overflow: auto;
}
@import "@react-aria/example-theme";

.color-picker {
  background: none;
  border: none;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  outline: none;
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1rem;
  color: var(--text-color);

  &[data-focus-visible] {
    outline: 2px solid var(--focus-ring-color);
    outline-offset: 2px;
  }
}

.color-picker-dialog {
  outline: none;
  padding: 15px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 192px;
  max-height: inherit;
  box-sizing: border-box;
  overflow: auto;
}

Features#


The <input type="color"> HTML element can be used to build a color picker, however it is very inconsistent across browsers and operating systems and does not allow customization. ColorPicker helps achieve accessible color pickers that can be styled as needed.

  • Customizable – Support for rendering any color picker UI by placing components like ColorArea, ColorSlider, ColorWheel, ColorField, and ColorSwatchPicker inside. These can be arranged in any desired combination or layout, with or without a popover.
  • Accessible – All color components announce localized color descriptions for screen reader users (e.g. "dark vibrant blue").

Anatomy#


A color picker does not render any UI by itself. You can render any combination of color components as children of a color picker, including ColorArea, ColorSlider, ColorWheel, ColorField, ColorSwatch, and ColorSwatchPicker. ColorPicker manages the state of the selected color, and coordinates the value between all of the components inside it.

import {ColorPicker} from 'react-aria-components';

<ColorPicker>
  {/* Color components here */}
</ColorPicker>
import {ColorPicker} from 'react-aria-components';

<ColorPicker>
  {/* Color components here */}
</ColorPicker>
import {ColorPicker} from 'react-aria-components';

<ColorPicker>
  {/* Color components here */}
</ColorPicker>

Reusable wrappers#


If you will use a ColorPicker in multiple places in your app, you can wrap all of the pieces into a reusable component. This way, the DOM structure, styling code, and other logic are defined in a single place and reused everywhere to ensure consistency.

This example wraps ColorPicker and all of its children together into a single component. It uses the reusable wrappers for ColorSwatch, ColorArea, ColorSlider, and ColorField created on their corresponding documentation pages. Custom children can also be provided to customize the layout within the popover.

import type {ColorPickerProps} from 'react-aria-components';
import {Button, ColorPicker, Dialog, DialogTrigger, Popover} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {MyColorField} from './ColorField';

interface MyColorPickerProps extends ColorPickerProps {
  label?: string;
  children?: React.ReactNode;
}

function MyColorPicker({ label, children, ...props }: MyColorPickerProps) {
  return (
    <ColorPicker {...props}>
      <DialogTrigger>
        <Button className="color-picker">
          <MyColorSwatch />
          <span>{label}</span>
        </Button>
        <Popover placement="bottom start">
          <Dialog className="color-picker-dialog">
            {children || (
              <>
                <MyColorArea
                  colorSpace="hsb"
                  xChannel="saturation"
                  yChannel="brightness"
                />
                <MyColorSlider colorSpace="hsb" channel="hue" />
                <MyColorField label="Hex" />
              </>
            )}
          </Dialog>
        </Popover>
      </DialogTrigger>
    </ColorPicker>
  );
}

<MyColorPicker label="Fill color" defaultValue="#f00" />
import type {ColorPickerProps} from 'react-aria-components';
import {
  Button,
  ColorPicker,
  Dialog,
  DialogTrigger,
  Popover
} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {MyColorField} from './ColorField';

interface MyColorPickerProps extends ColorPickerProps {
  label?: string;
  children?: React.ReactNode;
}

function MyColorPicker(
  { label, children, ...props }: MyColorPickerProps
) {
  return (
    <ColorPicker {...props}>
      <DialogTrigger>
        <Button className="color-picker">
          <MyColorSwatch />
          <span>{label}</span>
        </Button>
        <Popover placement="bottom start">
          <Dialog className="color-picker-dialog">
            {children || (
              <>
                <MyColorArea
                  colorSpace="hsb"
                  xChannel="saturation"
                  yChannel="brightness"
                />
                <MyColorSlider
                  colorSpace="hsb"
                  channel="hue"
                />
                <MyColorField label="Hex" />
              </>
            )}
          </Dialog>
        </Popover>
      </DialogTrigger>
    </ColorPicker>
  );
}

<MyColorPicker label="Fill color" defaultValue="#f00" />
import type {ColorPickerProps} from 'react-aria-components';
import {
  Button,
  ColorPicker,
  Dialog,
  DialogTrigger,
  Popover
} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {MyColorField} from './ColorField';

interface MyColorPickerProps
  extends
    ColorPickerProps {
  label?: string;
  children?:
    React.ReactNode;
}

function MyColorPicker(
  {
    label,
    children,
    ...props
  }: MyColorPickerProps
) {
  return (
    <ColorPicker
      {...props}
    >
      <DialogTrigger>
        <Button className="color-picker">
          <MyColorSwatch />
          <span>
            {label}
          </span>
        </Button>
        <Popover placement="bottom start">
          <Dialog className="color-picker-dialog">
            {children ||
              (
                <>
                  <MyColorArea
                    colorSpace="hsb"
                    xChannel="saturation"
                    yChannel="brightness"
                  />
                  <MyColorSlider
                    colorSpace="hsb"
                    channel="hue"
                  />
                  <MyColorField label="Hex" />
                </>
              )}
          </Dialog>
        </Popover>
      </DialogTrigger>
    </ColorPicker>
  );
}

<MyColorPicker
  label="Fill color"
  defaultValue="#f00"
/>

Value#


A ColorPicker 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.

Uncontrolled#

By default, ColorPicker is uncontrolled. You can set a default value using the defaultValue prop.

<MyColorPicker
  label="Color"
  defaultValue="hsl(25, 100%, 50%)" />
<MyColorPicker
  label="Color"
  defaultValue="hsl(25, 100%, 50%)" />
<MyColorPicker
  label="Color"
  defaultValue="hsl(25, 100%, 50%)"
/>

Controlled#

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 {parseColor} from 'react-aria-components';

function Example() {
  let [value, setValue] = React.useState(parseColor('hsl(25, 100%, 50%)'));
  return (
    <MyColorPicker
      label="Color"
      value={value}
      onChange={setValue} />
  );
}
import {parseColor} from 'react-aria-components';

function Example() {
  let [value, setValue] = React.useState(
    parseColor('hsl(25, 100%, 50%)')
  );
  return (
    <MyColorPicker
      label="Color"
      value={value}
      onChange={setValue}
    />
  );
}
import {parseColor} from 'react-aria-components';

function Example() {
  let [value, setValue] =
    React.useState(
      parseColor(
        'hsl(25, 100%, 50%)'
      )
    );
  return (
    <MyColorPicker
      label="Color"
      value={value}
      onChange={setValue}
    />
  );
}

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.

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

  return (
    <div>
      <MyColorPicker
        label="Color"
        value={value}
        onChange={setValue} />
      <p>Selected color: {value.toString('hsl')}</p>
    </div>
  );
}
function Example() {
  let [value, setValue] = React.useState(
    parseColor('hsl(50, 100%, 50%)')
  );

  return (
    <div>
      <MyColorPicker
        label="Color"
        value={value}
        onChange={setValue}
      />
      <p>Selected color: {value.toString('hsl')}</p>
    </div>
  );
}
function Example() {
  let [value, setValue] =
    React.useState(
      parseColor(
        'hsl(50, 100%, 50%)'
      )
    );

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

Examples#


Channel sliders#

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

import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorSlider} from './ColorSlider';
import {MyItem, MySelect} from './Select';

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

  return (
    <MyColorPicker label="Fill color" defaultValue="#184">
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) => setSpace(s as ColorSpace)}
      >
        <MyItem id="rgb">RGB</MyItem>
        <MyItem id="hsl">HSL</MyItem>
        <MyItem id="hsb">HSB</MyItem>
      </MySelect>
      {getColorChannels(space).map((channel) => (
        <MyColorSlider key={channel} colorSpace={space} channel={channel} />
      ))}
      <MyColorSlider channel="alpha" />    </MyColorPicker>
  );
}
import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorSlider} from './ColorSlider';
import {MyItem, MySelect} from './Select';

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

  return (
    <MyColorPicker label="Fill color" defaultValue="#184">
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) => setSpace(s as ColorSpace)}
      >
        <MyItem id="rgb">RGB</MyItem>
        <MyItem id="hsl">HSL</MyItem>
        <MyItem id="hsb">HSB</MyItem>
      </MySelect>
      {getColorChannels(space).map((channel) => (
        <MyColorSlider
          key={channel}
          colorSpace={space}
          channel={channel}
        />
      ))}
      <MyColorSlider channel="alpha" />    </MyColorPicker>
  );
}
import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorSlider} from './ColorSlider';
import {
  MyItem,
  MySelect
} from './Select';

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

  return (
    <MyColorPicker
      label="Fill color"
      defaultValue="#184"
    >
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) =>
          setSpace(
            s as ColorSpace
          )}
      >
        <MyItem id="rgb">
          RGB
        </MyItem>
        <MyItem id="hsl">
          HSL
        </MyItem>
        <MyItem id="hsb">
          HSB
        </MyItem>
      </MySelect>
      {getColorChannels(
        space
      ).map(
        (channel) => (
          <MyColorSlider
            key={channel}
            colorSpace={space}
            channel={channel}
          />
        )
      )}
      <MyColorSlider channel="alpha" />    </MyColorPicker>
  );
}

Color wheel#

This example combines a ColorWheel and ColorArea to build an HSB color picker.

import {MyColorWheel} from './ColorWheel';
import {MyColorArea} from './ColorArea';

<MyColorPicker label="Stroke color" defaultValue="#345">
  <MyColorWheel />
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    style={{
      width: '100px',
      height: '100px',
      position: 'absolute',
      top: 'calc(50% - 50px)',
      left: 'calc(50% - 50px)'
    }}
  />
</MyColorPicker>
import {MyColorWheel} from './ColorWheel';
import {MyColorArea} from './ColorArea';

<MyColorPicker label="Stroke color" defaultValue="#345">
  <MyColorWheel />
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    style={{
      width: '100px',
      height: '100px',
      position: 'absolute',
      top: 'calc(50% - 50px)',
      left: 'calc(50% - 50px)'
    }}
  />
</MyColorPicker>
import {MyColorWheel} from './ColorWheel';
import {MyColorArea} from './ColorArea';

<MyColorPicker
  label="Stroke color"
  defaultValue="#345"
>
  <MyColorWheel />
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
    style={{
      width: '100px',
      height: '100px',
      position:
        'absolute',
      top:
        'calc(50% - 50px)',
      left:
        'calc(50% - 50px)'
    }}
  />
</MyColorPicker>

Channel fields#

This example uses ColorField to allow a user to edit the value of each color channel as a number, along with a Select to switch between color spaces.

import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {MyItem, MySelect} from './Select';
import {MyColorField} from './ColorField';

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

  return (
    <MyColorPicker label="Color" defaultValue="#f80">
      <MyColorArea
        colorSpace="hsb"
        xChannel="saturation"
        yChannel="brightness"
      />
      <MyColorSlider colorSpace="hsb" channel="hue" />
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) => setSpace(s as ColorSpace)}
      >
        <MyItem id="rgb">RGB</MyItem>
        <MyItem id="hsl">HSL</MyItem>
        <MyItem id="hsb">HSB</MyItem>
      </MySelect>
      <div style={{ display: 'flex', gap: 4, width: 192 }}>
        {getColorChannels(space).map((channel) => (
          <MyColorField
            key={channel}
            colorSpace={space}
            channel={channel}
            style={{ flex: 1 }}
          />
        ))}      </div>
    </MyColorPicker>
  );
}
import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {MyItem, MySelect} from './Select';
import {MyColorField} from './ColorField';

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

  return (
    <MyColorPicker label="Color" defaultValue="#f80">
      <MyColorArea
        colorSpace="hsb"
        xChannel="saturation"
        yChannel="brightness"
      />
      <MyColorSlider colorSpace="hsb" channel="hue" />
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) => setSpace(s as ColorSpace)}
      >
        <MyItem id="rgb">RGB</MyItem>
        <MyItem id="hsl">HSL</MyItem>
        <MyItem id="hsb">HSB</MyItem>
      </MySelect>
      <div style={{ display: 'flex', gap: 4, width: 192 }}>
        {getColorChannels(space).map((channel) => (
          <MyColorField
            key={channel}
            colorSpace={space}
            channel={channel}
            style={{ flex: 1 }}
          />
        ))}      </div>
    </MyColorPicker>
  );
}
import type {ColorSpace} from 'react-aria-components';
import {getColorChannels} from 'react-aria-components';
import {MyColorArea} from './ColorArea';
import {MyColorSlider} from './ColorSlider';
import {
  MyItem,
  MySelect
} from './Select';
import {MyColorField} from './ColorField';

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

  return (
    <MyColorPicker
      label="Color"
      defaultValue="#f80"
    >
      <MyColorArea
        colorSpace="hsb"
        xChannel="saturation"
        yChannel="brightness"
      />
      <MyColorSlider
        colorSpace="hsb"
        channel="hue"
      />
      <MySelect
        aria-label="Color space"
        selectedKey={space}
        onSelectionChange={(s) =>
          setSpace(
            s as ColorSpace
          )}
      >
        <MyItem id="rgb">
          RGB
        </MyItem>
        <MyItem id="hsl">
          HSL
        </MyItem>
        <MyItem id="hsb">
          HSB
        </MyItem>
      </MySelect>
      <div
        style={{
          display:
            'flex',
          gap: 4,
          width: 192
        }}
      >
        {getColorChannels(
          space
        ).map(
          (channel) => (
            <MyColorField
              key={channel}
              colorSpace={space}
              channel={channel}
              style={{
                flex: 1
              }}
            />
          )
        )}      </div>
    </MyColorPicker>
  );
}

Swatches#

This example uses a ColorSwatchPicker to provide color presets for a color picker.

import {MyColorSwatchPicker, MyColorSwatchPickerItem} from './ColorSwatchPicker';

<MyColorPicker label="Color" defaultValue="#A00">
  <MyColorArea colorSpace="hsb" xChannel="saturation" yChannel="brightness" />
  <MyColorSlider colorSpace="hsb" channel="hue" />
  <MyColorSwatchPicker>
    <MyColorSwatchPickerItem color="#A00" />
    <MyColorSwatchPickerItem color="#f80" />
    <MyColorSwatchPickerItem color="#080" />
    <MyColorSwatchPickerItem color="#08f" />
    <MyColorSwatchPickerItem color="#008" />
  </MyColorSwatchPicker>
</MyColorPicker>
import {
  MyColorSwatchPicker,
  MyColorSwatchPickerItem
} from './ColorSwatchPicker';

<MyColorPicker label="Color" defaultValue="#A00">
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
  />
  <MyColorSlider colorSpace="hsb" channel="hue" />
  <MyColorSwatchPicker>
    <MyColorSwatchPickerItem color="#A00" />
    <MyColorSwatchPickerItem color="#f80" />
    <MyColorSwatchPickerItem color="#080" />
    <MyColorSwatchPickerItem color="#08f" />
    <MyColorSwatchPickerItem color="#008" />
  </MyColorSwatchPicker>
</MyColorPicker>
import {
  MyColorSwatchPicker,
  MyColorSwatchPickerItem
} from './ColorSwatchPicker';

<MyColorPicker
  label="Color"
  defaultValue="#A00"
>
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
  />
  <MyColorSlider
    colorSpace="hsb"
    channel="hue"
  />
  <MyColorSwatchPicker>
    <MyColorSwatchPickerItem color="#A00" />
    <MyColorSwatchPickerItem color="#f80" />
    <MyColorSwatchPickerItem color="#080" />
    <MyColorSwatchPickerItem color="#08f" />
    <MyColorSwatchPickerItem color="#008" />
  </MyColorSwatchPicker>
</MyColorPicker>

Props#


NameTypeDescription
valuestringColornullThe current value (controlled).
defaultValuestringColornullThe default value (uncontrolled).
childrenReactNode( (values: T{
defaultChildren: ReactNodeundefined
} )) => ReactNode
The children of the component. A function may be provided to alter the children based on component state.
Events
NameTypeDescription
onChange( (value: Color )) => voidHandler that is called when the value changes.
Layout
NameTypeDescription
slotstringnull

A slot name for the component. Slots allow the component to receive props from a parent component. An explicit null value indicates that the local props completely override all props received from a parent.

Advanced customization#


Contexts#

All React Aria Components export a corresponding context that can be used to send props to them from a parent element. This enables you to build your own compositional APIs similar to those found in React Aria Components itself. You can send any prop or ref via context that you could pass to the corresponding component. The local props and ref on the component are merged with the ones passed via context, with the local props taking precedence (following the rules documented in mergeProps).

ComponentContextPropsRef
ColorPickerColorPickerContextColorPickerProps

State#

ColorPicker provides a ColorPickerState object to its children via ColorPickerStateContext. This can be used to access and manipulate the color area's state.

This example uses the browser EyeDropper API (currently available in Chromium-based browsers) to allow users to sample on-screen colors. The ColorPicker is updated when the user chooses a color via the ColorPickerStateContext.

import {ColorPickerStateContext, parseColor} from 'react-aria-components';
import SamplerIcon from '@spectrum-icons/workflow/Sampler';

function EyeDropperButton() {
  let state = React.useContext(ColorPickerStateContext)!;

  // Check browser support.
  // @ts-ignore
  if (typeof EyeDropper === 'undefined') {
    return 'EyeDropper is not supported in your browser.';
  }

  return (
    <Button
      aria-label="Eye dropper"
      style={{ alignSelf: 'start' }}
      onPress={() => {
        // @ts-ignore
        new EyeDropper().open().then((result) =>
          state.setColor(parseColor(result.sRGBHex))
        );
      }}
    >
      <SamplerIcon size="S" />
    </Button>
  );
}

<MyColorPicker label="Color" defaultValue="#345">
  <MyColorArea colorSpace="hsb" xChannel="saturation" yChannel="brightness" />
  <MyColorSlider colorSpace="hsb" channel="hue" />
  <EyeDropperButton />
</MyColorPicker>
import {
  ColorPickerStateContext,
  parseColor
} from 'react-aria-components';
import SamplerIcon from '@spectrum-icons/workflow/Sampler';

function EyeDropperButton() {
  let state = React.useContext(ColorPickerStateContext)!;

  // Check browser support.
  // @ts-ignore
  if (typeof EyeDropper === 'undefined') {
    return 'EyeDropper is not supported in your browser.';
  }

  return (
    <Button
      aria-label="Eye dropper"
      style={{ alignSelf: 'start' }}
      onPress={() => {
        // @ts-ignore
        new EyeDropper().open().then((result) =>
          state.setColor(parseColor(result.sRGBHex))
        );
      }}
    >
      <SamplerIcon size="S" />
    </Button>
  );
}

<MyColorPicker label="Color" defaultValue="#345">
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
  />
  <MyColorSlider colorSpace="hsb" channel="hue" />
  <EyeDropperButton />
</MyColorPicker>
import {
  ColorPickerStateContext,
  parseColor
} from 'react-aria-components';
import SamplerIcon from '@spectrum-icons/workflow/Sampler';

function EyeDropperButton() {
  let state = React
    .useContext(
      ColorPickerStateContext
    )!;

  // Check browser support.
  // @ts-ignore
  if (
    typeof EyeDropper ===
      'undefined'
  ) {
    return 'EyeDropper is not supported in your browser.';
  }

  return (
    <Button
      aria-label="Eye dropper"
      style={{
        alignSelf:
          'start'
      }}
      onPress={() => {
        // @ts-ignore
        new EyeDropper()
          .open().then(
            (result) =>
              state
                .setColor(
                  parseColor(
                    result
                      .sRGBHex
                  )
                )
          );
      }}
    >
      <SamplerIcon size="S" />
    </Button>
  );
}

<MyColorPicker
  label="Color"
  defaultValue="#345"
>
  <MyColorArea
    colorSpace="hsb"
    xChannel="saturation"
    yChannel="brightness"
  />
  <MyColorSlider
    colorSpace="hsb"
    channel="hue"
  />
  <EyeDropperButton />
</MyColorPicker>