{/* Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:react-aria-components';
import statelyDocs from 'docs:@react-stately/color';
import {PropTable, HeaderInfo, TypeLink, PageDescription, StateTable, ContextTable} from '@react-spectrum/docs';
import styles from '@react-spectrum/docs/src/docs.css';
import packageData from 'react-aria-components/package.json';
import ChevronRight from '@spectrum-icons/workflow/ChevronRight';
import {Divider} from '@react-spectrum/divider';
import {ExampleList} from '@react-spectrum/docs/src/ExampleList';
import {ExampleCard} from '@react-spectrum/docs/src/ExampleCard';
import {Keyboard} from '@react-spectrum/text';
import {StarterKits} from '@react-spectrum/docs/src/StarterKits';

---
category: Color
keywords: [color swatch, color picker, aria]
type: component
---

# ColorSwatchPicker

<PageDescription>{docs.exports.ColorSwatchPicker.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['ColorSwatchPicker']}
  sourceData={[
    {type: 'W3C', url: 'https://www.w3.org/WAI/ARIA/apg/patterns/listbox/'}
  ]} />

## Example

```tsx example
import {ColorSwatchPicker, ColorSwatchPickerItem, ColorSwatch} from 'react-aria-components';

<ColorSwatchPicker>
  <ColorSwatchPickerItem color="#A00"><ColorSwatch /></ColorSwatchPickerItem>
  <ColorSwatchPickerItem color="#f80"><ColorSwatch /></ColorSwatchPickerItem>
  <ColorSwatchPickerItem color="#080"><ColorSwatch /></ColorSwatchPickerItem>
  <ColorSwatchPickerItem color="#08f"><ColorSwatch /></ColorSwatchPickerItem>
  <ColorSwatchPickerItem color="#088"><ColorSwatch /></ColorSwatchPickerItem>
  <ColorSwatchPickerItem color="#008"><ColorSwatch /></ColorSwatchPickerItem>
</ColorSwatchPicker>
```

<details>
  <summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>

```css hidden
@import "./ColorSwatch.mdx";
@import "./ColorField.mdx";
```

```css
@import "@react-aria/example-theme";

.react-aria-ColorSwatchPicker {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.react-aria-ColorSwatchPickerItem {
  position: relative;
  outline: none;
  border-radius: 4px;
  width: fit-content;
  forced-color-adjust: none;

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

  &[data-selected]::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 2px solid black;
    outline: 2px solid white;
    outline-offset: -4px;
    border-radius: inherit;
  }
}
```

</details>

## Features

A `ColorSwatchPicker` wraps the [ListBox](ListBox.html) component to simplify building color swatch pickers that work with a [ColorPicker](ColorPicker.html).

* **Item selection** – A single color value can be selected from a list of unique colors. Color swatches are automatically matched with the value no matter the color space they are defined in. 
* **Keyboard navigation** – Color swatches can be navigated using the arrow keys, along with page up/down, home/end, etc.
* **Layout options** – Items can be arranged in a vertical or horizontal stack, or as a two-dimensional grid.
* **Accessible** – Follows the [ARIA listbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/). Each swatch includes a localized color description for screen reader users (e.g. "dark vibrant blue").
* **Styleable** – Items include builtin states for styling, such as hover, press, focus, selected, and disabled.

## Anatomy

A ColorSwatchPicker consists of a container element, with a list of color swatches inside. Users can select a color by clicking, tapping, or navigating with the keyboard.

```tsx
import {ColorSwatchPicker, ColorSwatchPickerItem, ColorSwatch} from 'react-aria-components';

<ColorSwatchPicker>
  <ColorSwatchPickerItem>
    <ColorSwatch />
  </ColorSwatchPickerItem>
</ColorSwatchPicker>
```

ColorSwatchPicker is a convenience wrapper around the [ListBox](ListBox.html) component. If you need additional flexibility, such as support for multiple selection, duplicate colors, drag and drop, etc., you can use the ListBox component directly.

## Starter kits

To help kick-start your project, we offer starter kits that include example implementations of all React Aria components with various styling solutions. All components are fully styled, including support for dark mode, high contrast mode, and all UI states. Each starter comes with a pre-configured [Storybook](https://storybook.js.org/) that you can experiment with, or use as a starting point for your own component library.

<StarterKits component="colorswatchpicker" />

## Reusable wrappers

If you will use a ColorSwatchPicker 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 `ColorSwatchPicker` and `ColorSwatchPickerItem`, reusing the `MyColorSwatch` component from the [ColorSwatch](ColorSwatch.html#reusable-wrappers) docs.

```tsx example export=true
import type {ColorSwatchPickerProps, ColorSwatchPickerItemProps} from 'react-aria-components';
import {MyColorSwatch} from './ColorSwatch';

export function MyColorSwatchPicker({children, ...props}: ColorSwatchPickerProps) {
  return (
    <ColorSwatchPicker {...props}>
      {children}
    </ColorSwatchPicker>
  );
}

export function MyColorSwatchPickerItem(props: ColorSwatchPickerItemProps) {
  return (
    <ColorSwatchPickerItem {...props}>
      <MyColorSwatch />
    </ColorSwatchPickerItem>
  );
}

<MyColorSwatchPicker>
  <MyColorSwatchPickerItem color="#A00" />
  <MyColorSwatchPickerItem color="#f80" />
  <MyColorSwatchPickerItem color="#080" />
  <MyColorSwatchPickerItem color="#08f" />
  <MyColorSwatchPickerItem color="#088" />
  <MyColorSwatchPickerItem color="#008" />
</MyColorSwatchPicker>
```

## Value

ColorSwatchPicker accepts 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 <TypeLink links={docs.links} type={docs.exports.Color} /> object. The value is matched against the color of each ColorSwatch, including equivalent colors in different color spaces.

In the example below, the <TypeLink links={docs.links} type={docs.exports.parseColor} /> function is used to parse the initial color from a HSL string so that `value`'s type remains consistent.

```tsx example
import {parseColor} from 'react-aria-components';

function Example() {
  let [color, setColor] = React.useState(parseColor('hsl(0, 100%, 33.33%)'));

  return (
    <MyColorSwatchPicker value={color} onChange={setColor}>
      <MyColorSwatchPickerItem color="#A00" />
      <MyColorSwatchPickerItem color="#f80" />
      <MyColorSwatchPickerItem color="#080" />
    </MyColorSwatchPicker>
  );
}
```

**Note**: ColorSwatches rendered inside a ColorSwatchPicker must have unique colors, even between different color spaces. For example, the values `#f00`, `hsl(0, 100%, 50%)`, and `hsb(0, 100%, 100%)` are all equivalent and considered duplicates. This is required so that selection behavior works properly.

## Labeling

By default, `ColorSwatchPicker` has an `aria-label` with the localized string "Color swatches". This can be overridden with a more specific accessibility label using the `aria-label` or `aria-labelledby` props. All labels should be localized.

```tsx example
<MyColorSwatchPicker aria-label="Fill color">
  <MyColorSwatchPickerItem color="#A00" />
  <MyColorSwatchPickerItem color="#f80" />
  <MyColorSwatchPickerItem color="#080" />
</MyColorSwatchPicker>
```

## Events

ColorSwatchPicker accepts an `onChange` prop which is triggered whenever the value is edited by the user. It receives a <TypeLink links={docs.links} type={docs.exports.Color} /> object as a parameter.

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

```tsx example
import {parseColor} from 'react-aria-components';

function Example() {
  let [value, setValue] = React.useState(parseColor('#A00'));

  return (
    <div>
      <MyColorSwatchPicker value={value} onChange={setValue}>
        <MyColorSwatchPickerItem color="#A00" />
        <MyColorSwatchPickerItem color="#f80" />
        <MyColorSwatchPickerItem color="#080" />
        <MyColorSwatchPickerItem color="#08f" />
        <MyColorSwatchPickerItem color="#088" />
        <MyColorSwatchPickerItem color="#008" />
      </MyColorSwatchPicker>
      <p>Selected color: {value.toString('rgb')}</p>
    </div>
  );
}
```

## Disabled

A `ColorSwatchPickerItem` can be disabled using the `isDisabled` prop. Disabled swatches cannot be selected, and are not focusable or interactive.

```tsx example
<MyColorSwatchPicker>
  <MyColorSwatchPickerItem color="#A00" />
  <MyColorSwatchPickerItem color="#f80" isDisabled />
  <MyColorSwatchPickerItem color="#080" />
</MyColorSwatchPicker>
```

<details>
  <summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>

```css
.react-aria-ColorSwatchPickerItem {
  &[data-disabled] {
    opacity: 0.2;
  }
}
```

</details>

## Stack layout

By default, ColorSwatchPicker expects items to be arranged horizontally, optionally wrapping to form a grid, and implements keyboard navigation and drag and drop accordingly. The `layout` prop can be used to display the swatches as a vertical stack instead.

```tsx example
<MyColorSwatchPicker layout="stack">
  <MyColorSwatchPickerItem color="#A00" />
  <MyColorSwatchPickerItem color="#f80" />
  <MyColorSwatchPickerItem color="#080" />
  <MyColorSwatchPickerItem color="#08f" />
  <MyColorSwatchPickerItem color="#088" />
  <MyColorSwatchPickerItem color="#008" />
</MyColorSwatchPicker>
```

<details>
  <summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>

```css
.react-aria-ColorSwatchPicker {
  &[data-layout=stack] {
    flex-direction: column;
  }
}
```

</details>

## Props

### ColorSwatchPicker

<PropTable component={docs.exports.ColorSwatchPicker} links={docs.links} />

### ColorSwatchPickerItem

A `<ColorSwatchPickerItem>` represents an individual item within a `<ColorSwatchPicker>`. It should contain a `<ColorSwatch>`.

<PropTable component={docs.exports.ColorSwatchPickerItem} links={docs.links} />

## Styling

React Aria components can be styled in many ways, including using CSS classes, inline styles, utility classes (e.g. Tailwind), CSS-in-JS (e.g. Styled Components), etc. By default, all components include a builtin `className` attribute which can be targeted using CSS selectors. These follow the `react-aria-ComponentName` naming convention.

```css
.react-aria-ColorSwatchPicker {
  /* ... */
}
```

A custom `className` can also be specified on any component. This overrides the default `className` provided by React Aria with your own.

```jsx
<ColorSwatchPicker className="my-color-swatch-picker">
  {/* ... */}
</ColorSwatchPicker>
```

In addition, some components support multiple UI states (e.g. focused, placeholder, readonly, etc.). React Aria components expose states using data attributes, which you can target in CSS selectors. For example:

```css
.react-aria-ColorSwatchPickerItem[data-selected] {
  /* ... */
}
```

The `className` and `style` props also accept functions which receive states for styling. This lets you dynamically determine the classes or styles to apply, which is useful when using utility CSS libraries like [Tailwind](https://tailwindcss.com/).

```jsx
<ColorSwatchPickerItem className={({isSelected}) => isSelected ? 'border-black' : 'border-transparent'} />
```

The states, selectors, and render props for each component used in a `ColorSwatchPicker` are documented below.

### ColorSwatchPicker

The `ColorSwatchPicker` component can be targeted with the `.react-aria-ColorSwatchPicker` CSS selector, or by overriding with a custom `className`. It supports the following states:

<StateTable properties={docs.exports.ColorSwatchPickerRenderProps.properties} />

### ColorSwatchPickerItem

The `ColorSwatchPickerItem` component can be targeted with the `.react-aria-ColorSwatchPickerItem` CSS selector, or by overriding with a custom `className`. It supports the following states:

<StateTable properties={docs.exports.ColorSwatchPickerItemRenderProps.properties} />

### ColorSwatch

The `ColorSwatch` component can be targeted with the `.react-aria-ColorSwatch` CSS selector, or by overriding with a custom `className`. It supports the following states:

<StateTable properties={docs.exports.ColorSwatchRenderProps.properties} />

## Advanced customization

### Composition

If you need to customize one of the components within a `ColorSwatchPicker`, such as `ColorSwatchPickerItem` or `ColorSwatch`, in many cases you can create a wrapper component. This lets you customize the props passed to the component.

```tsx
function MyColorSwatchPickerItem(props) {
  return <ColorSwatchPickerItem {...props} className="my-swatch" />
}
```

### 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](mergeProps.html)).

<ContextTable components={['ColorSwatchPicker']} docs={docs} />

This example shows how to synchronize a ColorSwatchPicker and a [ColorField](ColorField.html) via context.

```tsx example
import {ColorSwatchPickerContext} from 'react-aria-components';
import {MyColorField} from './ColorField';

function ColorSelector({children}) {
  let [value, setValue] = React.useState(parseColor('#A00'));
  return (
    <div style={{display: 'flex', flexDirection: 'column', gap: 8}}>
      <MyColorField label="Color" value={value} onChange={setValue} />
      {/*- begin highlight -*/}
      <ColorSwatchPickerContext.Provider value={{value, onChange: setValue}}>
        {children}
      </ColorSwatchPickerContext.Provider>
      {/*- end highlight -*/}
    </div>
  );
}

<ColorSelector>
  <MyColorSwatchPicker>
    <MyColorSwatchPickerItem color="#A00" />
    <MyColorSwatchPickerItem color="#f80" />
    <MyColorSwatchPickerItem color="#080" />
  </MyColorSwatchPicker>
</ColorSelector>
```
