# ColorPicker

Lets users browse and select a color across a spectrum. Subcomponents: ColorArea, ColorSlider, AlphaSlider.

## Default

Source: CoreAI.

Selects a color and keeps HSV, RGB, hexadecimal, and alpha inputs synchronized.

[Download source](/coreai-design-system/source/examples/components-colorpicker--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorPickerProps } from "@coreai-ds/react-components";
import type { SpinButtonOnChangeData } from "@coreai-ds/react-components";
import type { SpinButtonChangeEvent } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";

export const Default = () => {
    type RgbKey = 'r' | 'g' | 'b';
    const hexColorRegex = /^#?([0-9A-Fa-f]{0,8})$/;
    const numberRegex = /^\d+$/;
    const defaultColorHsv = { h: 109, s: 1, v: 0.9, a: 1 };
    const hexId = useId('hex-input');
    const redId = useId('red-input');
    const greenId = useId('green-input');
    const blueId = useId('blue-input');
    const alphaId = useId('alpha-input');
    const [color, setColor] = React.useState(defaultColorHsv);
    const [hex, setHex] = React.useState(tinycolor(color).toHexString());
    const [rgb, setRgb] = React.useState(tinycolor(color).toRgb());
    const [alpha, setAlpha] = React.useState(color.a);
    const [namedColor, setNamedColor] = React.useState('');
    const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
        setColor({ ...data.color, a: data.color.a ?? 1 });
        setHex(tinycolor(data.color).toHexString());
        setRgb(tinycolor(data.color).toRgb());
        setAlpha(data.color.a ?? 1);
        const nextNamedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
        if (nextNamedColor) {
            setNamedColor(nextNamedColor);
        }
    };
    const onRgbChange = (name: RgbKey, data: SpinButtonOnChangeData) => {
        const value = data.value ?? parseFloat(data.displayValue ?? '');
        if (value === null || Number.isNaN(value) || !numberRegex.test(value.toString())) {
            return;
        }
        const newColor = tinycolor({ ...rgb, [name]: value });
        if (newColor.isValid) {
            setColor(newColor.toHsv());
            setHex(newColor.toHex());
            setRgb(newColor.toRgb());
        }
    };
    const onAlphaChange = React.useCallback((_event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => {
        const value = data.value ?? parseFloat(data.displayValue ?? '');
        if (Number.isNaN(value) || value < 0 || value > 1) {
            return;
        }
        const newColor = tinycolor({ ...color, a: value });
        if (newColor.isValid) {
            setColor(newColor.toHsv());
            setHex(newColor.toHex());
            setRgb(newColor.toRgb());
            setAlpha(newColor.a);
        }
    }, [color]);
    const handleOnBlur = (event: React.FocusEvent<HTMLInputElement>) => {
        const value = tinycolor(event.target.value);
        if (!value.isValid) {
            event.target.setAttribute('aria-invalid', 'true');
        }
        else {
            event.target.removeAttribute('aria-invalid');
        }
    };
    const colorAriaAttributes = {
        'aria-roledescription': '2D slider',
        'aria-valuetext': `Saturation ${color.s * 100}, Brightness: ${color.v * 100}, ${namedColor}`,
    };
    const rgbFields: Array<{
        id: string;
        label: string;
        name: RgbKey;
        value: number;
    }> = [
        { id: redId, label: 'Red', name: 'r', value: rgb.r },
        { id: greenId, label: 'Green', name: 'g', value: rgb.g },
        { id: blueId, label: 'Blue', name: 'b', value: rgb.b },
    ];
    const styles = /* css */ `
      .color-picker-default-example {
        width: 300px;
        display: flex;
        flex-direction: column;
        gap: 10px;
      }

      .color-picker-default-example__preview {
        width: 50px;
        height: 50px;
        border-radius: var(--borderRadiusMedium);
        border: 1px solid #ccc;
      }

      .color-picker-default-example__fields {
        display: flex;
        align-items: flex-end;
        flex-direction: row;
        gap: 10px;
      }

      .color-picker-default-example__field {
        display: flex;
        flex-direction: column;
        gap: var(--spacingHorizontalSNudge);
      }

      .color-picker-default-example__hex-input {
        width: 96px;
      }

      .color-picker-default-example__spin-button {
        min-width: 60px;
      }

      @media (forced-colors: active) {
        .color-picker-default-example__preview {
          forced-color-adjust: none;
        }
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="color-picker-default-example">
          <ColorPicker color={color} onColorChange={handleChange}>
            <ColorArea inputX={{ 'aria-label': 'Saturation', ...colorAriaAttributes }} inputY={{ 'aria-label': 'Brightness', ...colorAriaAttributes }}/>
            <ColorSlider aria-label="Hue" aria-valuetext={`${color.h}°, ${namedColor}`}/>
            <AlphaSlider aria-label="Alpha" aria-valuetext={`${color.a * 100}%`}/>
          </ColorPicker>
          <div className="color-picker-default-example__fields">
            <div className="color-picker-default-example__field">
              <Label htmlFor={hexId}>Hex</Label>
              <Input className="color-picker-default-example__hex-input" value={hex} id={hexId} onChange={(event) => {
            const value = event.target.value;
            const newColor = tinycolor(value);
            if (newColor.isValid) {
                setColor(newColor.toHsv());
                setRgb(newColor.toRgb());
                setAlpha(newColor.a);
            }
            setHex((oldValue) => (hexColorRegex.test(value) ? value : oldValue));
        }} onBlur={handleOnBlur}/>
            </div>
            {rgbFields.map((field) => (<div className="color-picker-default-example__field" key={field.name}>
                <Label htmlFor={field.id}>{field.label}</Label>
                <SpinButton className="color-picker-default-example__spin-button" min={0} max={255} value={field.value} id={field.id} onChange={(_, data) => onRgbChange(field.name, data)} name={field.name}/>
              </div>))}
            <div className="color-picker-default-example__field">
              <Label htmlFor={alphaId}>Alpha</Label>
              <SpinButton min={0} max={1} className="color-picker-default-example__spin-button" value={alpha} step={0.01} onChange={onAlphaChange} id={alphaId}/>
            </div>
          </div>
          <div className="color-picker-default-example__preview" style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
        </div>
      </>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### ColorPicker API

ColorPicker component

```ts
interface ColorPickerProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Selected color.
   */
  color?: HsvColor;

  /**
   * Callback for when the user changes the color.
   */
  onColorChange?: EventHandler<ColorPickerOnChangeData>;

  ref?: Ref<HTMLDivElement>;

  /**
   * ColorPicker shape
   */
  shape?: "rounded" | "square";

  style?: CSSProperties;
}
```

### AlphaSlider API

AlphaSlider component

```ts
interface AlphaSliderProps {
  as?: "input";

  children?: undefined;

  className?: string;

  /**
   * Color of the ColorPicker
   */
  color?: HsvColor;

  /**
   * The starting color for an uncontrolled ColorSlider.
   */
  defaultColor?: HsvColor;

  input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  /**
   * Triggers a callback when the value has been changed. This will be called on every individual step.
   */
  onChange?: EventHandler<SliderOnChangeData>;

  rail?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  ref?: Ref<HTMLInputElement>;

  root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * ColorPicker shape
   */
  shape?: "rounded" | "square";

  style?: CSSProperties;

  thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * The `transparency` property determines how the alpha channel is interpreted.
   * - When `false`, the alpha channel represents the opacity of the color.
   * - When `true`, the alpha channel represents the transparency of the color.
   * For example, a 30% transparent color has 70% opacity.
   */
  transparency?: boolean;

  /**
   * Render the Slider in a vertical orientation, smallest value on the bottom.
   * @default `false`
   */
  vertical?: boolean;
}
```

### ColorArea API

ColorArea component

```ts
interface ColorAreaProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * The current color of the ColorArea.
   */
  color?: HsvColor;

  /**
   * The starting value for an uncontrolled ColorArea.
   */
  defaultColor?: HsvColor;

  inputX?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  inputY?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  /**
   * Triggers a callback when the value has been changed. This will be called on every individual step.
   */
  onChange?: EventHandler<ColorAreaOnColorChangeData>;

  ref?: Ref<HTMLDivElement>;

  /**
   * ColorPicker shape
   */
  shape?: "rounded" | "square";

  style?: CSSProperties;

  thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;
}
```

### ColorSlider API

ColorSlider component

```ts
interface ColorSliderProps {
  as?: "input";

  /**
   * Color channel of the Slider.
   * @default `hue`
   */
  channel?: "value" | "hue" | "saturation";

  children?: undefined;

  className?: string;

  /**
   * Color of the ColorPicker
   */
  color?: HsvColor;

  /**
   * The starting color for an uncontrolled ColorSlider.
   */
  defaultColor?: HsvColor;

  input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  /**
   * Triggers a callback when the value has been changed. This will be called on every individual step.
   */
  onChange?: EventHandler<SliderOnChangeData>;

  rail?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  ref?: Ref<HTMLInputElement>;

  root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * ColorPicker shape
   */
  shape?: "rounded" | "square";

  style?: CSSProperties;

  thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * Render the Slider in a vertical orientation, smallest value on the bottom.
   * @default `false`
   */
  vertical?: boolean;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Alpha Slider Default

Source: Fluent, adapted for CoreAI.

The `AlphaSlider` allows users to change the alpha channel of a color value.

[Download source](/coreai-design-system/source/examples/components-colorpicker--alpha-slider-default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { AlphaSliderProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { AlphaSlider } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
import { Button } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const COLOR = { h: 96, s: 1, v: 0.9, a: 1 };

export const AlphaSliderDefault = (props: Partial<AlphaSliderProps>): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(COLOR);
    const [transparancyColor, setTransparancyColor] = React.useState(COLOR);
    const [value, setValue] = React.useState(COLOR.a * 100);
    const onSliderChange: AlphaSliderProps['onChange'] = (_, data) => {
        const alpha = data.color.a ?? 1;
        setColor({ ...data.color, a: alpha });
        setValue(alpha * 100);
    };
    const onTransparancySliderChange: AlphaSliderProps['onChange'] = (_, data) => setTransparancyColor({ ...data.color, a: data.color.a ?? 1 });
    const resetSlider = () => setColor(COLOR);
    const resetTransparencySlider = () => setTransparancyColor(COLOR);
    return (<div className={styles.example}>
      <AlphaSlider color={color} onChange={onSliderChange} aria-valuetext={`${value}%`} aria-label="Alpha" {...props}/>
      <AlphaSlider color={color} onChange={onSliderChange} aria-valuetext={`${value}%`} aria-label="Vertical alpha" vertical {...props}/>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
      <Button onClick={resetSlider}>Reset</Button>
      <h3>Transparency</h3>
      <AlphaSlider color={transparancyColor} onChange={onTransparancySliderChange} aria-valuetext={`${value}%`} aria-label="Alpha" transparency {...props}/>
      <AlphaSlider color={transparancyColor} onChange={onTransparancySliderChange} aria-valuetext={`${value}%`} aria-label="Vertical alpha" transparency vertical {...props}/>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(transparancyColor).toRgbString() }}/>
      <Button onClick={resetTransparencySlider}>Reset</Button>
    </div>);
};

export default AlphaSliderDefault;
```

## Color And Swatch Picker

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-and-swatch-picker.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorPickerProps } from "@coreai-ds/react-components";
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import { EmptySwatch } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: tokens.borderRadiusMedium,
        border: `1px solid ${tokens.colorNeutralStroke1}`,
        margin: `${tokens.spacingVerticalMNudge} 0`,
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
    button: {
        marginRight: tokens.spacingHorizontalS,
    },
    input: {
        display: 'block',
        margin: `${tokens.spacingVerticalSNudge} 0`,
    },
    row: {
        display: 'flex',
        gap: '10px',
        justifyContent: 'space-between',
    },
    sliders: {
        display: 'flex',
        flexDirection: 'column',
        width: '80%',
    },
});
const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };
const DEFAULT_SELECTED_VALUE = '2be700';
const DEFAULT_SELECTED_COLOR = tinycolor(DEFAULT_COLOR_HSV).toHex();
const ITEMS_LIMIT = 8;
export const ColorAndSwatchPicker = (): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const [selectedValue, setSelectedValue] = React.useState(DEFAULT_SELECTED_VALUE);
    const [selectedColor, setSelectedColor] = React.useState(DEFAULT_SELECTED_COLOR);
    const colorFocusTargetRef = React.useRef<HTMLButtonElement>(null);
    const [colorFocusTarget, setColorFocusTarget] = React.useState<string | null>(null);
    const [items, setItems] = React.useState<Array<{
        color: string;
        value: string;
        'aria-label': string;
    }>>([]);
    const emptyItems = new Array(ITEMS_LIMIT - items.length).fill(null);
    const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
        setColor({ ...data.color, a: data.color.a ?? 1 });
    };
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedColor(data.selectedSwatch);
    };
    const handleAddColor = () => {
        const newColor = tinycolor(color).toRgbString();
        const newValue = `custom-${newColor} [${items.length - ITEMS_LIMIT}]`;
        setItems([...items, { color: newColor, value: newValue, 'aria-label': newColor }]);
        setColorFocusTarget(newValue);
    };
    const resetColors = () => {
        setItems([]);
        setColorFocusTarget(null);
        setSelectedValue(DEFAULT_SELECTED_VALUE);
        setSelectedColor(DEFAULT_SELECTED_COLOR);
        setColor(DEFAULT_COLOR_HSV);
    };
    React.useEffect(() => {
        if (colorFocusTarget) {
            colorFocusTargetRef.current?.focus();
        }
    }, [colorFocusTarget]);
    return (<div className={styles.example}>
      <ColorPicker color={color} onColorChange={handleChange}>
        <ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
        <div className={styles.row}>
          <div className={styles.sliders}>
            <ColorSlider aria-label="Hue"/>
            <AlphaSlider aria-label="Alpha"/>
          </div>
          <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
        </div>
      </ColorPicker>
      <SwatchPicker aria-label="SwatchPicker with empty swatches" selectedValue={selectedValue} onSelectionChange={handleSelect} shape="rounded">
        {items.map(item => (<ColorSwatch key={item.value} ref={item.value === colorFocusTarget ? colorFocusTargetRef : null} {...item}/>))}
        {emptyItems.map((_, index) => (<EmptySwatch disabled key={index} aria-label="empty swatch"/>))}
      </SwatchPicker>
      <Label>Selected color</Label>
      <div className={styles.previewColor} style={{ backgroundColor: selectedColor }}/>
      <Button id="components-colorpicker--color-and-swatch-picker-add-new-color" className={styles.button} appearance="primary" disabled={items.length >= ITEMS_LIMIT} onClick={handleAddColor}>
        Add new color
      </Button>
      <Button id="components-colorpicker--color-and-swatch-picker-reset-example" className={styles.button} onClick={resetColors}>
        Reset example
      </Button>
    </div>);
};

export default ColorAndSwatchPicker;
```

## Color Area Default

Source: Fluent, adapted for CoreAI.

The `ColorArea` component allows users to adjust two channels of HSB color values against a two-dimensional gradient background.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-area-default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorAreaProps } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";
import { ColorArea } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: `1px solid ${tokens.colorNeutralStroke1}`,
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const DEFAULT_COLOR_HSV = { h: 324, s: 0.5, v: 0.5, a: 1 };

export const ColorAreaDefault = (): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const [namedColor, setNamedColor] = React.useState('');
    const onChange: ColorAreaProps['onChange'] = (_, data) => {
        setColor({ ...data.color, a: data.color.a ?? 1 });
        const _namedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
        if (_namedColor) {
            setNamedColor(_namedColor);
        }
    };
    const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
    const ariaAttributes = {
        'aria-roledescription': '2D slider',
        'aria-valuetext': `Saturation ${color.s * 100}, Brightness: ${color.v * 100}, ${namedColor}`,
    };
    return (<div className={styles.example}>
      <ColorArea color={color} onChange={onChange} inputX={{ 'aria-label': 'Saturation', ...ariaAttributes }} inputY={{ 'aria-label': 'Brightness', ...ariaAttributes }}/>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
      <Button onClick={resetSlider}>Reset</Button>
    </div>);
};

export default ColorAreaDefault;
```

## Color Picker Popup

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-picker-popup.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorPickerProps } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        margin: '10px 0',
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
    row: {
        display: 'flex',
        gap: '10px',
    },
    sliders: {
        display: 'flex',
        flexDirection: 'column',
    },
});

const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };

export const ColorPickerPopup = (): JSXElement => {
    const styles = useStyles();
    const [previewColor, setPreviewColor] = React.useState(DEFAULT_COLOR_HSV);
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
        setPreviewColor({ ...data.color, a: data.color.a ?? 1 });
    };
    const [popoverOpen, setPopoverOpen] = React.useState(false);
    return (<>
      <Popover open={popoverOpen} trapFocus onOpenChange={(_, data) => setPopoverOpen(data.open)}>
        <PopoverTrigger disableButtonEnhancement>
          <Button>Choose color</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <ColorPicker color={previewColor} onColorChange={handleChange}>
            <ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
            <div className={styles.row}>
              <div className={styles.sliders}>
                <ColorSlider aria-label="Hue"/>
                <AlphaSlider aria-label="Alpha"/>
              </div>
              <div className={styles.previewColor} style={{ backgroundColor: tinycolor(previewColor).toRgbString() }}/>
            </div>
          </ColorPicker>
          <div className={styles.row}>
            <Button appearance="primary" onClick={() => {
            setColor(previewColor);
            setPopoverOpen(false);
        }}>
              Ok
            </Button>
            <Button onClick={() => {
            setPopoverOpen(false);
        }}>
              Cancel
            </Button>
          </div>
        </PopoverSurface>
      </Popover>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
    </>);
};

export default ColorPickerPopup;
```

## Color Picker Shape

Source: Fluent, adapted for CoreAI.

The `shape` prop sets border-radius of the ColorPicker sub-components. The default is `rounded`.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-picker-shape.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ColorPickerProps } from "@coreai-ds/react-components";
import { ColorPicker } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { AlphaSlider } from "@coreai-ds/react-components";
import { ColorArea } from "@coreai-ds/react-components";
import { tinycolor } from "@ctrl/tinycolor";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.91, a: 1 };

export const ColorPickerShape = (): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const handleChange: ColorPickerProps['onColorChange'] = (_, data) => setColor({ ...data.color, a: data.color.a ?? 1 });
    return (<div className={styles.example}>
      <h3>Rounded (default)</h3>
      <ColorPicker color={color} onColorChange={handleChange}>
        <ColorSlider aria-label="Hue"/>
        <AlphaSlider aria-label="Alpha"/>
        <ColorArea inputX={{ 'aria-label': 'Saturation' }} inputY={{ 'aria-label': 'Brightness' }}/>
      </ColorPicker>
      <h3>Square (default)</h3>
      <ColorPicker shape="square" color={color} onColorChange={handleChange}>
        <ColorArea />
        <ColorSlider />
        <AlphaSlider />
      </ColorPicker>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
    </div>);
};

export default ColorPickerShape;
```

## Color Slider Channels

Source: Fluent, adapted for CoreAI.

The `ColorSlider` allows users to choose color channels like hue, saturation, and value.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-slider-channels.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import type { ColorSliderProps } from "@coreai-ds/react-components";
import { ColorSlider } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
    },
});

const DEFAULT_COLOR_HSV = tinycolor('#2be700').toHsv();

export const ColorSliderChannels = (): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const onSliderChange: ColorSliderProps['onChange'] = (_, data) => {
        setColor({ ...data.color, a: data.color.a ?? 1 });
    };
    const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
    return (<div className={styles.example}>
      <h4>Hue</h4>
      <ColorSlider color={color} onChange={onSliderChange}/>
      <h4>Saturation</h4>
      <ColorSlider color={color} channel="saturation" onChange={onSliderChange}/>
      <h4>Value (Brightness)</h4>
      <ColorSlider color={color} channel="value" onChange={onSliderChange}/>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
      <Button onClick={resetSlider}>Reset</Button>
    </div>);
};

export default ColorSliderChannels;
```

## Color Slider Default

Source: Fluent, adapted for CoreAI.

The `ColorSlider` allows users to change the hue aspect of a color value.

[Download source](/coreai-design-system/source/examples/components-colorpicker--color-slider-default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { ColorSliderProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { tinycolor } from "@ctrl/tinycolor";
import { ColorSlider } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    previewColor: {
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const DEFAULT_COLOR_HSV = { h: 109, s: 1, v: 0.9, a: 1 };

export const ColorSliderDefault = (props: Partial<ColorSliderProps>): JSXElement => {
    const styles = useStyles();
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    const [hue, setHue] = React.useState(DEFAULT_COLOR_HSV.h);
    const [namedColor, setNamedColor] = React.useState('');
    const onSliderChange: ColorSliderProps['onChange'] = (_, data) => {
        setColor({ ...data.color, a: data.color.a ?? 1 });
        setHue(data.color.h);
        const _namedColor = tinycolor(`hsl(${data.color.h},100%,50%)`).toName();
        if (_namedColor) {
            setNamedColor(_namedColor);
        }
    };
    const resetSlider = () => setColor(DEFAULT_COLOR_HSV);
    return (<div className={styles.example}>
      <ColorSlider color={color} onChange={onSliderChange} aria-label="Hue" aria-valuetext={`${hue}°, ${namedColor}`} {...props}/>
      <ColorSlider color={color} onChange={onSliderChange} vertical aria-label="Vertical Hue" aria-valuetext={`${hue}°, ${namedColor}`} {...props}/>
      <div className={styles.previewColor} style={{ backgroundColor: tinycolor(color).toHexString() }}/>
      <Button onClick={resetSlider}>Reset</Button>
    </div>);
};

export default ColorSliderDefault;
```