Skip to Content

Color picker

A panel containing swatches for selecting colors.

import * as React from 'react';
import {
  ColorBuilder,
  ColorInputPanel,
  ColorPicker,
  ColorValue,
  IconButton,
  ColorSwatch,
  Popover,
} from '@itwin/itwinui-react';

export default () => {
  const [activeColor, setActiveColor] = React.useState(
    ColorValue.create('#0073ba'),
  );

  const onColorChanged = (color) => {
    setActiveColor(color);
  };

  return (
    <Popover
      content={
        <ColorPicker
          selectedColor={activeColor}
          onChangeComplete={onColorChanged}
        >
          <ColorBuilder />
          <ColorInputPanel defaultColorFormat={'hsl'} />
        </ColorPicker>
      }
    >
      <IconButton label='Show color picker'>
        <ColorSwatch style={{ pointerEvents: 'none' }} color={activeColor} />
      </IconButton>
    </Popover>
  );
};

Color pickers allow users to browse and apply a color to a selected item.

Variants

Basic

A basic color picker displays a pre-determined selection of colors. Because the colors are system-provided, each color should have a user friendly name. The user cannot add or remove swatches from what is available in the basic color picker. You may offer a transparent / no color option.

import * as React from 'react';
import {
  ColorPalette,
  ColorPicker,
  ColorSwatch,
  Button,
  Popover,
} from '@itwin/itwinui-react';

export default () => {
  const ColorsList = [
    { color: '#ffffff', name: 'WHITE' },
    { color: '#5a6973', name: 'GREY' },
    { color: '#00121d', name: 'KURETAKE BLACK MANGA' },
    { color: '#002a44', name: 'RHAPSODY IN BLUE' },
    { color: '#00426b', name: 'DARK IMPERIAL BLUE' },
    { color: '#005a92', name: 'JETSKI RACE' },
    { color: '#0073ba', name: 'FRENCH BLUE' },
    { color: '#008be1', name: 'BLUE COLA' },
    { color: '#30b0ff', name: 'FANTASY CONSOLE SKY' },
    { color: '#58bfff', name: 'HELLO SUMMER' },
    { color: '#7fceff', name: 'CHROMIS DAMSEL BLUE' },
    { color: '#a6ddff', name: 'DROPLET' },
    { color: '#cdecff', name: 'LUCID DREAMS' },
    { color: '#e5f5fd', name: 'KODAMA WHITE' },
    { color: '#010200', name: 'REGISTRATION BLACK' },
    { color: '#122306', name: 'YUZU SOY' },
    { color: '#23450b', name: 'FOREST GREEN' },
    { color: '#346711', name: 'TATZELWURM GREEN' },
    { color: '#458816', name: 'CHLOROPHYLL' },
    { color: '#56aa1c', name: 'PLASTIC PINES' },
    { color: '#5fbb1f', name: 'FIELD GREEN' },
    { color: '#67cc22', name: 'GREEN HIGH' },
    { color: '#91e458', name: 'LILLIPUTIAN LIME' },
    { color: '#b2ec8b', name: 'GREEN DAY' },
    { color: '#d4f4bd', name: 'TEA GREEN' },
    { color: '#eef6e8', name: 'VERDE PASTEL' },
    { color: '#9ba5af', name: 'SERYI GREY' },
    { color: '#cf0000', name: 'RED EPIPHYLLUM' },
    { color: '#ff6300', name: 'SAFETY ORANGE' },
    { color: '#ffc335', name: 'RISE-N-SHINE' },
  ];

  const [isOpen, setIsOpen] = React.useState(false);
  const [activeColor, setActiveColor] = React.useState(ColorsList[5]);
  const [colorName, setColorName] = React.useState(ColorsList[5].name);

  const onColorChanged = (color) => {
    const hexString = color.toHexString();
    const index = ColorsList.findIndex(
      (swatch) => swatch.color === hexString.toLowerCase(),
    );
    setActiveColor(ColorsList[index]);
    setColorName(ColorsList[index].name);
    setIsOpen(false);
  };

  return (
    <Popover
      visible={isOpen}
      onVisibleChange={setIsOpen}
      content={
        <ColorPicker
          selectedColor={activeColor.color}
          onChangeComplete={onColorChanged}
        >
          <ColorPalette colors={ColorsList.map(({ color }) => color)} />
        </ColorPicker>
      }
    >
      <Button
        startIcon={
          <ColorSwatch
            className='demo-color-swatch'
            color={activeColor.color}
          />
        }
      >
        {colorName}
      </Button>
    </Popover>
  );
};

Advanced

The advanced color picker lets the user pick any color. You may display user saved colors or recently used colors if needed. Because the colors are immensely flexible, colors are labeled with HEX, RGB/RGBA, or HSL/HSLA color code values. A clickable icon in the text field allows the user to rotate through the different color code types.

import * as React from 'react';
import {
  ColorBuilder,
  ColorInputPanel,
  ColorPalette,
  ColorPicker,
  ColorValue,
} from '@itwin/itwinui-react';

export default () => {
  const [selectedColor, setSelectedColor] = React.useState(
    ColorValue.create({ r: 90, g: 105, b: 115, a: 0.4 }),
  );

  const onColorChanged = (color) => {
    setSelectedColor(color);
  };

  return (
    <ColorPicker
      selectedColor={selectedColor}
      onChangeComplete={onColorChanged}
      showAlpha={true}
    >
      <ColorBuilder />
      <ColorInputPanel defaultColorFormat='rgb' />
      <ColorPalette
        label='Saved Colors'
        colors={[
          { r: 90, g: 105, b: 115, a: 1 },
          { r: 90, g: 105, b: 115, a: 0.81 },
          { r: 90, g: 105, b: 115, a: 0.4 },
        ]}
      />
    </ColorPicker>
  );
};

The color code can be displayed in editable fields for precise color selection. There are two ways to show this code: within the panel itself as seen in the example above, or in a dropdown button/input field combo, like below. If the color code is shown outside of the panel, do not include the color code within the panel at the same time.

import * as React from 'react';
import {
  ColorBuilder,
  ColorPalette,
  ColorPicker,
  ColorValue,
  ButtonGroup,
  ColorSwatch,
  IconButton,
  Button,
} from '@itwin/itwinui-react';
import { Popover } from '@itwin/itwinui-react';
import { SvgSwap } from '@itwin/itwinui-icons-react';

export default () => {
  const [isOpen, setIsOpen] = React.useState(false);
  const [selectedColor, setSelectedColor] = React.useState(
    ColorValue.create({ h: 0, s: 100, l: 50 }),
  );

  const formats = ['hsl', 'rgb', 'hex'];
  const [currentFormat, setCurrentFormat] = React.useState(formats[0]);

  const onColorChanged = (color) => {
    setSelectedColor(color);
  };

  const getDisplayString = (color = selectedColor) => {
    switch (currentFormat) {
      case 'hsl':
        return color.toHslString(true);
      case 'rgb':
        return color.toRgbString(true);
      case 'hex':
        return color.toHexString(true);
    }
  };

  return (
    <>
      <ButtonGroup>
        <Popover
          content={
            <ColorPicker
              selectedColor={selectedColor}
              onChangeComplete={onColorChanged}
            >
              <ColorBuilder />
              <ColorPalette
                label='Saved Colors'
                colors={[
                  { h: 0, s: 100, l: 50 },
                  { r: 255, g: 98, b: 0 },
                  '#fec134',
                  '#5A6973',
                  { h: 95, s: 83, v: 72 },
                  { h: 250, s: 100, l: 59 },
                ]}
              />
            </ColorPicker>
          }
          portal={{ to: () => document.body }}
          visible={isOpen}
          onVisibleChange={setIsOpen}
          placement='bottom-start'
        >
          <IconButton label='Show color picker'>
            <ColorSwatch color={selectedColor} className='demo-color-swatch' />
          </IconButton>
        </Popover>
        <Button
          onClick={() => {
            setCurrentFormat(
              formats[(formats.indexOf(currentFormat) + 1) % formats.length],
            );
          }}
          endIcon={<SvgSwap />}
        >
          <div className='demo-label'>
            {getDisplayString() ?? 'No color selected.'}
          </div>
        </Button>
      </ButtonGroup>
    </>
  );
};

Props

Prop Description Default
children
Content of the color palette.
Pass a combination of ColorBuilder, ColorInputPanel, ColorPalette, and any custom children.
ReactNode
selectedColor
The selected color within color picker.
ColorType | ColorValue
onChange
Callback fired when the color value is internally updated during operations like dragging a thumb. Use this callback with caution as a high-volume of updates will occur when dragging.
(color: ColorValue) => void
onChangeComplete
Callback fired when selectedColor is done changing. This can be on pointerUp or keyUp when thumb is done dragging, or when user clicks on color builder components, or when user clicks on color swatch.
(color: ColorValue) => void
showAlpha
If true, ColorBuilder will show the alpha slider and ColorInputPanel will show an alpha input.
boolean
false
applyBackground
Whether there is a background, border, shadow, etc.
Should be set to true if used in a popover that doesn't have its own background, or set to false if the popover has its own background or embedding within a page.
boolean
true
as
"symbol" | "object" | "search" | "big" | "link" | "small" | "sub" | "sup" | "g" | "b" | "a" | "s" | "div" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "base" | "bdi" | ... 157 more ... | FunctionComponent<...>

Subcomponents

The color picker is extremely flexible; pieces can be used based on product requirements. If certain parts are not required for your context, they can be left out. There are no hard guidelines for what an advanced color picker contains. It should remain usable and align with the user’s workflow.

Color Builder

ColorBuilder consists of two parts: a color canvas to adjust saturation and lightness values, and a set of sliders to adjust hue and alpha values.

Prop Description Default
colorFieldProps
Passes props to the color field.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
colorDotProps
Passes props to the color dot.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
opacitySliderProps
Passes props to the color opacity slider.
Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: Ref<...>; }, "as" | keyof SliderProps> & SliderProps & { ...; }
hueSliderProps
Passes props to the color hue slider.
Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: Ref<...>; }, "as" | keyof SliderProps> & SliderProps & { ...; }
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>

Color Input Panel

ColorInputPanel shows input fields to enter precise color values in the specified format. It also allows switching between the specified formats using a swap button.

Prop Description Default
defaultColorFormat
The default color format to be inputted in the panel.
"hsl" | "rgb" | "hex"
allowedColorFormats
Color formats to switch between. The swap button will cycle between these formats.
If array only has one option, then swap button will not be shown.
("hsl" | "rgb" | "hex")[]
['hsl', 'rgb', 'hex']
panelLabelProps
Passes props to the color picker section label.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
colorInputContainerProps
Passes props to the color input container.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
inputFieldsGroupProps
Passes props to the color input fields group.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
swapColorFormatButtonProps
Passes props to the swap color format button.
Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ...; }, "label" | ... 8 more ... | "iconProps"> & { ...; } & Omit<...> & { ...; }
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>

Color Palette

ColorPalette is used to show a group of ColorSwatch components.

Prop Description Default
label
Label shown above the palette.
ReactNode
labelProps
Passes props to the color picker section label.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
colors
List of colors shown as swatches in the palette.
(ColorType | ColorValue)[]
children
Pass any custom swatches as children.
ReactNode
paletteContainerProps
Passes props to the color palette container.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>

Color Swatch

ColorSwatch is a component to display within a color palette.

Prop Description Default
color
Color code.
ColorValue | ColorType
isActive
Is color selected.
boolean
as
"symbol" | "object" | "button" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "canvas" | ... 159 more ... | FunctionComponent<...>