Default

Loading interactive example. Full source is available below.

View example source
Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";

export const Default = () => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedColor, setSelectedColor] = React.useState('#00B053');
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedColor(data.selectedSwatch);
    };
    const styles = /* css */ `
      .swatch-picker-default-example__preview {
        width: 100px;
        height: 100px;
        border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
        margin: var(--spacingVerticalL) 0;
      }

      @media (forced-colors: active) {
        .swatch-picker-default-example__preview {
          forced-color-adjust: none;
        }
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="swatch-picker-default-example">
          <SwatchPicker aria-label="SwatchPicker default" selectedValue={selectedValue} onSelectionChange={handleSelect}>
            <ColorSwatch color="#FF1921" value="FF1921" aria-label="red"/>
            <ColorSwatch color="#FF7A00" value="FF7A00" aria-label="orange"/>
            <ColorSwatch color="#90D057" value="90D057" aria-label="light green"/>
            <ColorSwatch color="#00B053" value="00B053" aria-label="green"/>
            <ColorSwatch color="#00AFED" value="00AFED" aria-label="light blue"/>
            <ColorSwatch color="#006EBD" value="006EBD" aria-label="blue"/>
            <ColorSwatch disabled color="#011F5E" value="011F5E" aria-label="dark blue"/>
            <ColorSwatch color="#712F9E" value="712F9E" aria-label="purple"/>
          </SwatchPicker>

          <div className="swatch-picker-default-example__preview" style={{ backgroundColor: selectedColor }}/>
        </div>
      </>);
};

export default Default;

Resources

Best practices

Do

  • Use no more than eight swatches in a row.
  • Use a grid for more than four swatches, capped at an 8×8 grid.
  • Show a tooltip for each color.
  • Provide labels through aria-label or a tooltip.

Don't

  • Use rounded corners in grid layouts.
  • Space extra-small or smaller swatches less than 4px apart.
  • Display more than four disabled swatches.

Behavior and states

  • The SwatchPicker can be integrated within a popover or used as a standalone feature.
API referenceGenerated CoreAI prop and type summaries

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.

SwatchPicker API

interface SwatchPickerProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * Default selected value
   */
  defaultSelectedValue?: string;

  /**
   * Sets the focus behavior for the SwatchPicker.
   *
   * `arrow`
   * This behavior will cycle through all elements inside of the SwatchPicker when pressing the Arrow key.
   *
   * `tab`
   * This behavior will cycle through all elements inside of the SwatchPicker when pressing the Tab key.
   * @default 'arrow'
   */
  focusMode?: "tab" | "arrow";

  /**
   * Whether SwatchPicker is row or grid
   */
  layout?: "grid" | "row";

  /**
   * Triggers a callback when the value has been changed
   */
  onSelectionChange?: EventHandler<SwatchPickerOnSelectionChangeData>;

  ref?: Ref<HTMLDivElement>;

  /**
   * Controlled selected value
   */
  selectedValue?: string;

  /**
   * Swatch shape.
   * @default 'rounded'
   */
  shape?: "circular" | "rounded" | "square";

  /**
   * Swatch size
   */
  size?: "small" | "medium" | "large" | "extra-small";

  /**
   * Spacing between swatches
   */
  spacing?: "small" | "medium";

  style?: CSSProperties;
}

ColorSwatch API

ColorSwatch component is used to render a colors, icons and gradients.

interface ColorSwatchProps {
  as?: "button";

  /**
   * Border color when contrast is low
   */
  borderColor?: string;

  children?: any;

  className?: string;

  /**
   * Swatch color
   */
  color?: string;

  /**
   * Whether the swatch is disabled
   */
  disabled?: boolean;

  disabledIcon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  icon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLButtonElement>;

  /**
   * Swatch shape
   */
  shape?: "circular" | "rounded" | "square";

  /**
   * Swatch size
   */
  size?: "small" | "medium" | "large" | "extra-small";

  style?: CSSProperties;

  /**
   * Swatch value
   */
  value?: string | number | readonly string[];
}

EmptySwatch API

EmptySwatch component is used for adding new color swatches.

interface EmptySwatchProps {
  as?: "button";

  children?: any;

  className?: string;

  ref?: Ref<HTMLButtonElement>;

  /**
   * Swatch shape
   */
  shape?: "circular" | "rounded" | "square";

  /**
   * Swatch size
   */
  size?: "small" | "medium" | "large" | "extra-small";

  style?: CSSProperties;
}

ImageSwatch API

ImageSwatch component is used to render an images, patterns and textures.

interface ImageSwatchProps {
  as?: "button";

  children?: any;

  className?: string;

  ref?: Ref<HTMLButtonElement>;

  /**
   * Swatch shape
   */
  shape?: "circular" | "rounded" | "square";

  /**
   * Swatch size
   */
  size?: "small" | "medium" | "large" | "extra-small";

  /**
   * Swatch color
   */
  src: string;

  style?: CSSProperties;

  /**
   * Swatch value
   */
  value?: string | number | readonly string[];
}

SwatchPickerRow API

SwatchPickerRow component is used to render a row of swatches.

interface SwatchPickerRowProps {
  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}

Implementation

CoreAI 0.12.0; Fluent 9.74.9.

Setup and dependencies.

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

Color Swatch Variants

Loading interactive example. Full source is available below.

Download source
// 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 { ColorSwatch } from "@coreai-ds/react-components";
import { HeartFilled } from "@fluentui/react-icons";
import * as React from 'react';

const useStyles = makeStyles({
    example: {
        display: 'flex',
        gap: '8px',
    },
    icon: {
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

export const ColorSwatchVariants = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.example}>
      <ColorSwatch color="#E3008C" value="hot-pink-color" aria-label="Hot pink"/>
      <ColorSwatch color="linear-gradient(0deg, #E3008C, #fff232)" value="gradient" aria-label="Gradient yellow pink"/>
      <ColorSwatch color="#c8eeff" icon={<HeartFilled color="red" className={styles.icon}/>} value="icon" aria-label="heart icon"/>
      <ColorSwatch color="#016ab0" disabled value="blue" aria-label="blue"/>
      <ColorSwatch color="#ff659a" value="initials" aria-label="initials">
        A
      </ColorSwatch>
      <ColorSwatch disabled color="#c8eeff" value="light-blue" aria-label="light blue"/>
    </div>);
};

export default ColorSwatchVariants;

Empty Swatch Example

Loading interactive example. Full source is available below.

Download source
// 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 { ColorPickerProps } from "@coreai-ds/react-components";
import type { SwatchPickerOnSelectEventHandler } 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 { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Tooltip } 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";
const useStyles = makeStyles({
    example: {
        width: '300px',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
    selectedColor: {
        width: '100px',
        height: '100px',
        border: '1px solid #ccc',
        margin: '20px 0',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
    button: {
        marginRight: '8px',
    },
    previewColor: {
        margin: '10px 0',
        width: '50px',
        height: '50px',
        borderRadius: '4px',
        border: '1px solid #ccc',
    },
    previewButton: {
        minWidth: '50px',
        height: '50px',
        display: 'block',
        margin: '10px 0',
    },
    rowWrapper: {
        display: 'flex',
        gap: '10px',
    },
    sliders: {
        display: 'flex',
        flexDirection: 'column',
    },
});
const DEFAULT_COLOR_HSV = tinycolor('#2be700').toHsv();
const defaultItems = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'dark orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
];
const ITEMS_LIMIT = 8;
export const EmptySwatchExample = (): JSXElement => {
    const styles = useStyles();
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedColor, setSelectedColor] = React.useState('#00B053');
    const [popoverOpen, setPopoverOpen] = React.useState(false);
    const [previewColor, setPreviewColor] = React.useState(DEFAULT_COLOR_HSV);
    const [color, setColor] = React.useState(DEFAULT_COLOR_HSV);
    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;
    }>>(defaultItems);
    const emptyItems = new Array(ITEMS_LIMIT - items.length).fill(null);
    const handleChange: ColorPickerProps['onColorChange'] = (_, data) => {
        setPreviewColor({ ...data.color, a: data.color.a ?? 1 });
    };
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedColor(data.selectedSwatch);
    };
    const handleAddColor = () => {
        const newColor = tinycolor(color).toRgbString();
        // "value" should be unique as it's used as a key and for selection
        const newValue = `custom-${newColor} [${items.length - ITEMS_LIMIT}]`;
        setItems([...items, { color: newColor, value: newValue, 'aria-label': newColor }]);
        setColorFocusTarget(newValue);
    };
    const resetColors = () => {
        setItems(defaultItems);
        setColorFocusTarget(selectedValue);
    };
    React.useEffect(() => {
        if (colorFocusTarget) {
            colorFocusTargetRef.current?.focus();
        }
    }, [colorFocusTarget]);
    return (<>
      <SwatchPicker aria-label="SwatchPicker with empty swatches" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {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>
      <h4>Selected swatch</h4>
      <div className={styles.selectedColor} style={{ backgroundColor: selectedColor }}/>
      <Popover open={popoverOpen} trapFocus onOpenChange={(_, data) => setPopoverOpen(data.open)}>
        <PopoverTrigger disableButtonEnhancement>
          <Tooltip content="Custom color" relationship="label">
            <Button className={styles.previewButton} style={{ backgroundColor: tinycolor(color).toRgbString() }}/>
          </Tooltip>
        </PopoverTrigger>

        <PopoverSurface>
          <ColorPicker color={previewColor} onColorChange={handleChange}>
            <ColorArea />
            <div className={styles.rowWrapper}>
              <div className={styles.sliders}>
                <ColorSlider />
                <AlphaSlider />
              </div>
              <div className={styles.previewColor} style={{ backgroundColor: tinycolor(previewColor).toRgbString() }}/>
            </div>
          </ColorPicker>
          <div className={styles.rowWrapper}>
            <Button appearance="primary" onClick={() => {
            setColor(previewColor);
            setPopoverOpen(false);
        }}>
              Ok
            </Button>
            <Button onClick={() => {
            setPopoverOpen(false);
        }}>
              Cancel
            </Button>
          </div>
        </PopoverSurface>
      </Popover>

      <Button id="components-swatchpicker--empty-swatch-example-add-new-color" className={styles.button} appearance="primary" disabled={items.length >= ITEMS_LIMIT} onClick={handleAddColor}>
        Add new color
      </Button>
      <Button id="components-swatchpicker--empty-swatch-example-reset-example" className={styles.button} onClick={resetColors}>
        Reset example
      </Button>
    </>);
};

export default EmptySwatchExample;

Swatch Picker Focus Mode

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
];

export const SwatchPickerFocusMode = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
    };
    return (<>
      <h3>Arrow navigation (default)</h3>
      <SwatchPicker focusMode="arrow" aria-label="SwatchPicker with arrow navigation" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {colors.map(color => (<ColorSwatch key={color.value} {...color}/>))}
      </SwatchPicker>
      <h3>Tab navigation</h3>
      <SwatchPicker focusMode="tab" aria-label="SwatchPicker with tab navigation" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {colors.map(color => (<ColorSwatch key={color.value} {...color}/>))}
      </SwatchPicker>
    </>);
};

export default SwatchPickerFocusMode;

Swatch Picker Image

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ImageSwatch } from "@coreai-ds/react-components";

const DEFAULT_IMAGE = 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-full-img.jpg';

const images = [
    {
        swatchSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/sea-swatch.jpg',
        value: '0',
        label: 'sea',
        fullImageSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/sea-full-img.jpg',
    },
    {
        swatchSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-swatch.jpg',
        value: '1',
        label: 'bridge',
        fullImageSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-full-img.jpg',
    },
    {
        swatchSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/park-swatch.jpg',
        value: '2',
        label: 'park',
        fullImageSrc: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/park-full-img.jpg',
    },
];

const useStyles = makeStyles({
    example: {
        width: '100%',
        height: '466px',
        backgroundSize: 'contain',
        backgroundRepeat: 'no-repeat',
        margin: '20px 0',
    },
    swatch: {
        width: '100px',
        height: '100px',
        '@media (max-width: 768px)': {
            width: '50px',
            height: '50px',
        },
    },
});

export const SwatchPickerImage = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('1');
    const [selectedImage, setSelectedImage] = React.useState(DEFAULT_IMAGE);
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        const image = images.find(img => img.value === data.selectedValue) || images[0];
        setSelectedImage(image.fullImageSrc);
    };
    const styles = useStyles();
    return (<>
      <SwatchPicker aria-label="SwatchPicker with images" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {images.map(image => (<ImageSwatch className={styles.swatch} key={image.value} src={image.swatchSrc} value={image.value} aria-label={image.label}/>))}
      </SwatchPicker>
      <div className={styles.example} style={{
            backgroundImage: `url(${selectedImage})`,
        }}/>
    </>);
};

export default SwatchPickerImage;

Swatch Picker Layout

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import { renderSwatchPickerGrid } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '100px',
        height: '100px',
        border: '1px solid #ccc',
        margin: '20px 0',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#011F5E', value: '011F5E', 'aria-label': 'dark blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
    { color: '#FF0099', value: 'FF0099', 'aria-label': 'pink' },
];

export const SwatchPickerLayout = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedSwatch, setSelectedSwatch] = React.useState('#00B053');
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedSwatch(data.selectedSwatch);
    };
    const styles = useStyles();
    return (<>
      <h3>Row</h3>
      <SwatchPicker aria-label="SwatchPicker row layout" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {colors.map(color => {
            return <ColorSwatch key={color.value} {...color}/>;
        })}
      </SwatchPicker>
      <h3>Grid</h3>
      <SwatchPicker layout="grid" aria-label="SwatchPicker grid layout" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {renderSwatchPickerGrid({
            items: colors,
            columnCount: 3,
        })}
      </SwatchPicker>
      <div className={styles.example} style={{
            background: selectedSwatch,
        }}/>
    </>);
};

export default SwatchPickerLayout;

Swatch Picker Mixed Swatches

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import type { SwatchProps } from "@coreai-ds/react-components";
import type { ColorSwatchProps } from "@coreai-ds/react-components";
import type { ImageSwatchProps } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import { renderSwatchPickerGrid } from "@coreai-ds/react-components";

const colors: ColorSwatchProps[] = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
];

const images: ImageSwatchProps[] = [
    {
        src: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/sea-swatch.jpg',
        value: 'sea',
        'aria-label': 'sea',
    },
    {
        src: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-swatch.jpg',
        value: 'bridge',
        'aria-label': 'bridge',
    },
    {
        src: 'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/park-swatch.jpg',
        value: 'park',
        'aria-label': 'park',
    },
];

const items: SwatchProps[] = [...colors, ...images];

const useStyles = makeStyles({
    example: {
        width: '100px',
        height: '100px',
        border: '1px solid #ccc',
        margin: '20px 0',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

export const SwatchPickerMixedSwatches = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedSwatch, setSelectedSwatch] = React.useState('#00B053');
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        const swatch = items.find(item => item.value === data.selectedValue) || items[0];
        const src = (swatch as ImageSwatchProps).src;
        if (swatch.color) {
            setSelectedSwatch(swatch.color);
        }
        else if (src) {
            setSelectedSwatch(`url(${src}`);
        }
    };
    const styles = useStyles();
    return (<>
      <SwatchPicker layout="grid" aria-label="SwatchPicker with both colors and images" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {renderSwatchPickerGrid({
            items,
            columnCount: 3,
        })}
      </SwatchPicker>
      <div className={styles.example} style={{
            background: selectedSwatch,
        }}/>
    </>);
};

export default SwatchPickerMixedSwatches;

Swatch Picker Popup

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { makeStyles } 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 { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import { renderSwatchPickerGrid } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '100px',
        height: '100px',
        border: '1px solid #ccc',
        margin: '20px 0',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const colorSet1 = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
];

const colorSet2 = [
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'dark orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#3BC4F5', value: '3BC4F5', 'aria-label': 'light blue 10' },
    { color: '#1F93E6', value: '1F93E6', 'aria-label': 'blue 10' },
    { color: '#A01CFa', value: 'A01CFa', 'aria-label': 'bright purple' },
    {
        color: 'linear-gradient(0deg, #FF1921, #FFB92E)',
        value: 'orange-red',
        'aria-label': 'gradient orange-red',
    },
    {
        color: 'linear-gradient(0deg, #00B053, #90D057)',
        value: 'light-green-gradient',
        'aria-label': 'gradient light green',
    },
    {
        color: 'linear-gradient(0deg, #006EBD, #00AFED)',
        value: 'blue gradient',
        'aria-label': 'gradient blue',
    },
    {
        color: 'linear-gradient(0deg, #712F9E, #00AFED)',
        value: 'blue-purple',
        'aria-label': 'gradient blue-purple',
    },
    {
        color: 'linear-gradient(0deg, #fA1CBC, #A01CFa)',
        value: 'blue-purple',
        'aria-label': 'gradient pink-purple',
    },
    {
        color: 'linear-gradient(0deg, #FFC12E, #FEFF37)',
        value: 'yellow-orange',
        'aria-label': 'gradient yellow-orange',
    },
    {
        color: 'linear-gradient(0deg, #90D057, #FEFF37)',
        value: 'yellow-green',
        'aria-label': 'gradient yellow-green',
    },
    {
        color: 'linear-gradient(0deg, #00B053, #00AFED)',
        value: 'green-blue',
        'aria-label': 'gradient green-blue',
    },
    {
        color: 'linear-gradient(0deg, #A01CFA, #00AFED)',
        value: 'blue-purple gradient',
        'aria-label': 'gradient blue',
    },
    {
        color: 'linear-gradient(0deg, #FF1921 0%, #FFC12E 10%, #FEFF37 20%, #90D057 30%, #00B053 40%, #00AFED 50%, #006EBD 60%, #011F5E 70%, #712F9E 80%)',
        value: 'gradient',
        'aria-label': 'gradient rainbow',
    },
];

export const SwatchPickerPopup = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedColor, setSelectedColor] = React.useState('#00B053');
    const [popoverOpen, setPopoverOpen] = React.useState(false);
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedColor(data.selectedSwatch);
        setPopoverOpen(false);
    };
    const styles = useStyles();
    return (<>
      <Popover open={popoverOpen} trapFocus onOpenChange={(_, data) => setPopoverOpen(data.open)}>
        <PopoverTrigger disableButtonEnhancement>
          <Button>Choose color</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <h3>Color set 1</h3>
          <SwatchPicker aria-label="SwatchPicker set 1" selectedValue={selectedValue} onSelectionChange={handleSelect}>
            {colorSet1.map((color, index) => {
            return <ColorSwatch key={`${color.value}-${index}`} {...color}/>;
        })}
          </SwatchPicker>
          <h3>Color set 2</h3>
          <SwatchPicker layout="grid" aria-label="SwatchPicker set 2" selectedValue={selectedValue} onSelectionChange={handleSelect}>
            {renderSwatchPickerGrid({
            items: colorSet2,
            columnCount: 5,
        })}
          </SwatchPicker>
        </PopoverSurface>
      </Popover>
      <div className={styles.example} style={{
            background: selectedColor,
        }}/>
    </>);
};

export default SwatchPickerPopup;

Swatch Picker Shape

Loading interactive example. Full source is available below.

Download source
// 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 { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    example: {
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
});

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'dark orange' },
    { color: '#FFC12E', value: 'FFC12E', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#011F5E', value: '011F5E', 'aria-label': 'dark blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
];

export const SwatchPickerShape = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.example}>
      <h3>Square</h3>
      <SwatchPicker aria-label="SwatchPicker square shape">
        {colors.map(color => (<ColorSwatch key={color.value} {...color}/>))}
      </SwatchPicker>
      <h3>Circular</h3>
      <SwatchPicker aria-label="SwatchPicker circular shape" shape="circular">
        {colors.map(color => (<ColorSwatch key={color.value} {...color}/>))}
      </SwatchPicker>
      <h3>Rounded</h3>
      <SwatchPicker aria-label="SwatchPicker rounded shape" shape="rounded">
        {colors.map(color => (<ColorSwatch key={color.value} {...color}/>))}
      </SwatchPicker>
    </div>);
};

export default SwatchPickerShape;

Swatch Picker Size

Loading interactive example. Full source is available below.

Download source
// 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 { SwatchPicker } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    example: {
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
});

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#011F5E', value: '011F5E', 'aria-label': 'dark blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
];

export const SwatchPickerSize = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.example}>
      <h3>Large</h3>
      <SwatchPicker aria-label="SwatchPicker large size" size="large">
        {colors.map(color => {
            return <ColorSwatch key={color.value} {...color}/>;
        })}
      </SwatchPicker>
      <h3>Medium</h3>
      <SwatchPicker aria-label="SwatchPicker medium size">
        {colors.map(color => {
            return <ColorSwatch key={color.value} {...color}/>;
        })}
      </SwatchPicker>
      <h3>Small</h3>
      <SwatchPicker aria-label="SwatchPicker small size" size="small">
        {colors.map(color => {
            return <ColorSwatch key={color.value} {...color}/>;
        })}
      </SwatchPicker>
      <h3>Extra small</h3>
      <SwatchPicker aria-label="SwatchPicker extra small size" size="extra-small">
        {colors.map(color => {
            return <ColorSwatch key={color.value} {...color}/>;
        })}
      </SwatchPicker>
    </div>);
};

export default SwatchPickerSize;

Swatch Picker Spacing

Loading interactive example. Full source is available below.

Download source
// 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 { SwatchPicker } from "@coreai-ds/react-components";
import { renderSwatchPickerGrid } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    example: {
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
    },
});

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'dark orange' },
    { color: '#FFC12E', value: 'FFC12E', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#011F5E', value: '011F5E', 'aria-label': 'dark blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
];

export const SwatchPickerSpacing = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.example}>
      <h3>Medium</h3>
      <SwatchPicker layout="grid" aria-label="SwatchPicker medium spacing">
        {renderSwatchPickerGrid({
            items: colors,
            columnCount: 3,
        })}
      </SwatchPicker>
      <h3>Small</h3>
      <SwatchPicker layout="grid" aria-label="SwatchPicker small spacing" spacing="small">
        {renderSwatchPickerGrid({
            items: colors,
            columnCount: 3,
        })}
      </SwatchPicker>
    </div>);
};

export default SwatchPickerSpacing;

Swatch Picker With Tooltip

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SwatchPickerOnSelectEventHandler } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { SwatchPicker } from "@coreai-ds/react-components";
import type { ColorSwatchProps } from "@coreai-ds/react-components";
import { Tooltip } from "@coreai-ds/react-components";
import { ColorSwatch } from "@coreai-ds/react-components";
import { renderSwatchPickerGrid } from "@coreai-ds/react-components";
import type { SwatchProps } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    example: {
        width: '100px',
        height: '100px',
        border: '1px solid #ccc',
        margin: '20px 0',
        '@media (forced-colors: active)': {
            forcedColorAdjust: 'none',
        },
    },
});

const colors = [
    { color: '#FF1921', value: 'FF1921', 'aria-label': 'red' },
    { color: '#FF7A00', value: 'FF7A00', 'aria-label': 'orange' },
    { color: '#90D057', value: '90D057', 'aria-label': 'light green' },
    { color: '#00B053', value: '00B053', 'aria-label': 'green' },
    { color: '#00AFED', value: '00AFED', 'aria-label': 'light blue' },
    { color: '#006EBD', value: '006EBD', 'aria-label': 'blue' },
    { color: '#011F5E', value: '011F5E', 'aria-label': 'dark blue' },
    { color: '#712F9E', value: '712F9E', 'aria-label': 'purple' },
    { color: '#FF0099', value: 'FF0099', 'aria-label': 'pink' },
];

const ColorSwatchWithTooltip = (props: ColorSwatchProps) => {
    const { color, value } = props;
    const label = props['aria-label'] ?? 'color swatch';
    return (<Tooltip withArrow content={label} relationship="label">
      <ColorSwatch color={color} value={value}/>
    </Tooltip>);
};

export const SwatchPickerWithTooltip = (): JSXElement => {
    const [selectedValue, setSelectedValue] = React.useState('00B053');
    const [selectedColor, setSelectedColor] = React.useState('#00B053');
    const handleSelect: SwatchPickerOnSelectEventHandler = (_, data) => {
        setSelectedValue(data.selectedValue);
        setSelectedColor(data.selectedSwatch);
    };
    const styles = useStyles();
    return (<>
      <h3>Row layout</h3>
      <SwatchPicker aria-label="SwatchPicker row layout" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {colors.map(color => {
            return <ColorSwatchWithTooltip key={color.value} {...color}/>;
        })}
      </SwatchPicker>
      <h3>Grid layout</h3>
      <SwatchPicker layout="grid" aria-label="SwatchPicker grid layout" selectedValue={selectedValue} onSelectionChange={handleSelect}>
        {renderSwatchPickerGrid({
            items: colors,
            columnCount: 3,
            renderSwatch: ({ color = '', ...item }: SwatchProps) => (<ColorSwatchWithTooltip key={item.value} color={color} {...item}/>),
        })}
      </SwatchPicker>

      <div className={styles.example} style={{
            backgroundColor: selectedColor,
        }}/>
    </>);
};

export default SwatchPickerWithTooltip;