{/* Copyright 2020 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/select';
import selectUtil from 'docs:@react-aria/test-utils';
import {PropTable, HeaderInfo, TypeLink, PageDescription, StateTable, ContextTable, ClassAPI, VersionBadge} from '@react-spectrum/docs';
import styles from '@react-spectrum/docs/src/docs.css';
import packageData from 'react-aria-components/package.json';
import Anatomy from './SelectAnatomy.svg';
import ChevronRight from '@spectrum-icons/workflow/ChevronRight';
import {Divider} from '@react-spectrum/divider';
import {ExampleCard} from '@react-spectrum/docs/src/ExampleCard';
import {ExampleList} from '@react-spectrum/docs/src/ExampleList';
import Button from '@react-spectrum/docs/pages/assets/component-illustrations/ActionButton.svg';
import Label from '@react-spectrum/docs/pages/assets/component-illustrations/Label.svg';
import Popover from '@react-spectrum/docs/pages/assets/component-illustrations/Popover.svg';
import ListBox from '@react-spectrum/docs/pages/assets/component-illustrations/ListBox.svg';
import Collections from '@react-spectrum/docs/pages/assets/component-illustrations/Collections.svg';
import Selection from '@react-spectrum/docs/pages/assets/component-illustrations/Selection.svg';
import Form from '@react-spectrum/docs/pages/assets/component-illustrations/Form.svg';
import {StarterKits} from '@react-spectrum/docs/src/StarterKits';

---
category: Pickers
keywords: [listbox, select, aria]
type: component
---

# Select

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

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

## Example

```tsx example
import {Select, SelectValue, Label, Button, Popover, ListBox, ListBoxItem} from 'react-aria-components';
import {ChevronDown} from 'lucide-react';

<Select>
  <Label>Favorite Animal</Label>
  <Button>
    <SelectValue />
    <span aria-hidden="true"><ChevronDown size={16} /></span>
  </Button>
  <Popover>
    <ListBox>
      <ListBoxItem>Aardvark</ListBoxItem>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
      <ListBoxItem>Panda</ListBoxItem>
      <ListBoxItem>Snake</ListBoxItem>
    </ListBox>
  </Popover>
</Select>
```

<details>
  <summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>
```css hidden
@import './ListBox.mdx' layer(listbox);
@import './Popover.mdx' layer(popover);
@import './Button.mdx' layer(button);
@import './Form.mdx' layer(form);
```

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

.react-aria-Select {
  color: var(--text-color);
  max-width: 250px;
  width: fit-content;

  .react-aria-Button {
    box-shadow: 0 1px 2px rgba(0 0 0 / 0.1);
    border-radius: 6px;
    font-size: 1.072rem;
    padding: 0.286rem 0.286rem 0.286rem 0.571rem;
    display: flex;
    align-items: center;
    width: 100%;

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

  .react-aria-SelectValue {
    flex: 1;
    text-align: start;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;

    &[data-placeholder] {
      font-style: italic;
      color: var(--text-color-placeholder);
    }
  }

  span[aria-hidden] {
    width: 1.429rem;
    height: 1.429rem;
    line-height: 1.375rem;
    margin-left: 1rem;
    padding: 1px;
    background: var(--highlight-background);
    color: var(--highlight-foreground);
    forced-color-adjust: none;
    border-radius: 4px;
    font-size: 0.857rem;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
}

.react-aria-Popover[data-trigger=Select] {
  min-width: var(--trigger-width);
  --starting-scale: scale(1);

  .react-aria-ListBox {
    display: block;
    width: unset;
    max-height: inherit;
    min-height: unset;
    border: none;

    .react-aria-Header {
      padding-left: 1.571rem;
    }
  }

  .react-aria-ListBoxItem {
    padding: 0 0.571rem 0 1.571rem;

    &[data-focus-visible] {
      outline: none;
    }

    &[data-selected] {
      font-weight: 600;
      background: unset;
      color: var(--text-color);

      &::before {
        content: '✓';
        content: '✓' / '';
        alt: ' ';
        position: absolute;
        top: 4px;
        left: 4px;
      }
    }

    &[data-focused],
    &[data-pressed] {
      background: var(--highlight-background);
      color: var(--highlight-foreground);
    }
  }
}
```

</details>

## Features

A select can be built using the [&lt;select&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
and [&lt;option&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option) HTML elements, but this is
not possible to style consistently cross browser, especially the options. `Select` helps achieve accessible
select components that can be styled as needed without compromising on high quality interactions.

* **Flexible** – Support for controlled and uncontrolled state, async loading, disabled items, validation, sections, complex items, and more.
* **Keyboard navigation** – Select can be opened and navigated using the arrow keys, along with page up/down, home/end, etc. Auto scrolling, and typeahead both in the listbox and on the button, are supported as well.
* **Accessible** – Follows the [ARIA listbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/), with support for items and sections, and slots for label and description elements within each item for improved screen reader announcement.
* **HTML form integration** – A visually hidden `<select>` element is included to enable HTML form integration and autofill.
* **Validation** – Support for native HTML constraint validation with customizable UI, custom validation functions, and server-side validation errors.
* **Styleable** – Items include builtin states for styling, such as hover, press, focus, selected, and disabled.

## Anatomy

<Anatomy />

A select consists of a label, a button which displays a selected value, and a listbox, displayed in a
popover. Users can click, touch, or use the keyboard on the button to open the listbox popover.

`Select` also supports optional description and error message elements, which can be used
to provide more context about the field, and any validation messages. These are linked with the
input via the `aria-describedby` attribute.

```tsx
import {Select, SelectValue, Label, Button, Popover, ListBox, ListBoxItem, ListBoxSection, Header, Text, FieldError} from 'react-aria-components';

<Select>
  <Label />
  <Button>
    <SelectValue />
  </Button>
  <Text slot="description" />
  <FieldError />
  <Popover>
    <ListBox>
      <ListBoxItem>
        <Text slot="label" />
        <Text slot="description" />
      </ListBoxItem>
      <ListBoxSection>
        <Header />
        <ListBoxItem />
      </ListBoxSection>
    </ListBox>
  </Popover>
</Select>
```

If a select does not have a visible label, an `aria-label` or `aria-labelledby`
prop must be passed instead to identify it to assistive technology.

### Concepts

`Select` makes use of the following concepts:

<section className={styles.cardGroup} data-size="small">

<ExampleCard
  url="collections.html"
  title="Collections"
  description="Defining collections of items, async loading, and updating items over time.">
  <Collections />
</ExampleCard>

<ExampleCard
  url="selection.html"
  title="Selection"
  description="Interactions and data structures to represent selection.">
  <Selection />
</ExampleCard>

<ExampleCard
  url="forms.html"
  title="Forms"
  description="Validating and submitting form data, and integrating with form libraries.">
  <Form />
</ExampleCard>

</section>

### Composed components

A `Select` uses the following components, which may also be used standalone or reused in other components.

<section className={styles.cardGroup} data-size="small">

<ExampleCard
  url="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label"
  title="Label"
  description="A label provides context for an input element.">
  <Label />
</ExampleCard>

<ExampleCard
  url="Button.html"
  title="Button"
  description="A button allows a user to perform an action.">
  <Button />
</ExampleCard>

<ExampleCard
  url="Popover.html"
  title="Popover"
  description="A popover displays content in context with a trigger element.">
  <Popover />
</ExampleCard>

<ExampleCard
  url="ListBox.html"
  title="ListBox"
  description="A listbox allows a user to select one or more options from a list.">
  <ListBox />
</ExampleCard>

</section>

## Examples

<ExampleList tag="select" />

## 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="select" />

## Reusable wrappers

If you will use a Select 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 `Select` and all of its children together into a single component which accepts a `label` prop and `children`, which are passed through to the right places. It also shows how to use the `description` slot to render [help text](#description), and `FieldError` component to render [validation errors](#validation). The `Item` component is also wrapped to apply class names based on the current state, as described in the [styling](#styling) section.

```tsx example export=true
import type {SelectProps, ListBoxItemProps, ValidationResult} from 'react-aria-components';
import {Text, FieldError} from 'react-aria-components';

interface MySelectProps<T extends object, M extends 'single' | 'multiple'> extends Omit<SelectProps<T, M>, 'children'> {
  label?: string,
  description?: string,
  errorMessage?: string | ((validation: ValidationResult) => string),
  items?: Iterable<T>,
  children: React.ReactNode | ((item: T) => React.ReactNode)
}

export function MySelect<T extends object, M extends 'single' | 'multiple' = 'single'>(
  {label, description, errorMessage, children, items, ...props}: MySelectProps<T, M>
) {
  return (
    <Select {...props}>
      <Label>{label}</Label>
      <Button>
        <SelectValue />
        <span aria-hidden="true"><ChevronDown size={16} /></span>
      </Button>
      {description && <Text slot="description">{description}</Text>}
      <FieldError>{errorMessage}</FieldError>
      <Popover>
        <ListBox items={items}>
          {children}
        </ListBox>
      </Popover>
    </Select>
  );
}

export function MyItem(props: ListBoxItemProps) {
  return <ListBoxItem {...props} className={({isFocused, isSelected}) => `my-item ${isFocused ? 'focused' : ''} ${isSelected ? 'selected' : ''}`} />
}

<MySelect label="Ice cream flavor">
  <MyItem>Chocolate</MyItem>
  <MyItem>Mint</MyItem>
  <MyItem>Strawberry</MyItem>
  <MyItem>Vanilla</MyItem>
</MySelect>
```

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

```css
.my-item {
  margin: 2px;
  padding: 4px 8px 4px 22px;
  border-radius: 6px;
  outline: none;
  cursor: default;
  color: var(--text-color);
  font-size: 1.072rem;
  position: relative;

  &.selected {
    font-weight: 600;
    background: none;

    &::before {
      content: '✓';
      content: '✓' / '';
      alt: ' ';
      position: absolute;
      top: 4px;
      left: 4px;
    }
  }

  &.focused {
    background: #e70073;
    color: white;
  }
}

@media (forced-colors: active) {
  .my-item.focused {
    background: Highlight;
    color: HighlightText;
  }
}
```

</details>

## Content

`Select` follows the [Collection Components API](collections.html), accepting both static and dynamic collections.
The examples above show static collections, which can be used when the full list of options is known ahead of time. Dynamic collections,
as shown below, can be used when the options come from an external data source such as an API call, or update over time.

As seen below, an iterable list of options is passed to the Select using the `items` prop. Each item accepts an `id` prop, which
is passed to the `onChange` handler to identify the selected item. Alternatively, if the item objects contain an `id` property,
as shown in the example below, then this is used automatically and an `id` prop is not required.

```tsx example
function Example() {
  let options = [
    {id: 1, name: 'Aerospace'},
    {id: 2, name: 'Mechanical'},
    {id: 3, name: 'Civil'},
    {id: 4, name: 'Biomedical'},
    {id: 5, name: 'Nuclear'},
    {id: 6, name: 'Industrial'},
    {id: 7, name: 'Chemical'},
    {id: 8, name: 'Agricultural'},
    {id: 9, name: 'Electrical'}
  ];

  return (
    <MySelect label="Pick an engineering major" items={options}>
      {(item) => <ListBoxItem>{item.name}</ListBoxItem>}
    </MySelect>
  );
}
```

## Value

Setting a selected option can be done by using the `defaultValue` or `value` prop. The value corresponds to the `id` prop of an item.
When `Select` is used with a dynamic collection as described above, the id of each item is derived from the data.

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

function Example() {
  let options = [
    {name: 'Koala'},
    {name: 'Kangaroo'},
    {name: 'Platypus'},
    {name: 'Bald Eagle'},
    {name: 'Bison'},
    {name: 'Skunk'}
  ];
  let [animal, setAnimal] = React.useState<Key>("Bison");

  return (
    <MySelect
      label="Pick an animal (controlled)"
      items={options}
      value={animal}
      onChange={selected => setAnimal(selected)}>
      {item => <ListBoxItem id={item.name}>{item.name}</ListBoxItem>}
    </MySelect>
  );
}
```

### Multiple selection

Set the `selectionMode="multiple"` prop to enable the user to select multiple items. When multiple selection is enabled, the `value` prop should be an array of item ids instead of a single item, and `onChange` will be called with an array. See [below](#customizing-selectvalue) for how to customize the `SelectValue`.

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

function Example() {
  let options = [
    {name: 'Koala'},
    {name: 'Kangaroo'},
    {name: 'Platypus'},
    {name: 'Bald Eagle'},
    {name: 'Bison'},
    {name: 'Skunk'}
  ];
  /*- begin highlight -*/
  let [animals, setAnimals] = React.useState<Key[]>(['Bison', 'Kangaroo']);
  /*- end highlight -*/

  return (
    <MySelect
      label="Pick an animal (controlled)"
      items={options}
      /*- begin highlight -*/
      selectionMode="multiple"
      /*- end highlight -*/
      value={animals}
      onChange={selected => setAnimals(selected)}>
      {item => <ListBoxItem id={item.name}>{item.name}</ListBoxItem>}
    </MySelect>
  );
}
```

### HTML forms

Select supports the `name` prop for integration with HTML forms. The `id` of the selected item will be submitted to the server.

```tsx example
<MySelect
  label="Favorite Animal"
  ///- begin highlight -///
  name="favoriteAnimalId"
  ///- end highlight -///
>
  <ListBoxItem id="panda">Panda</ListBoxItem>
  <ListBoxItem id="cat">Cat</ListBoxItem>
  <ListBoxItem id="dog">Dog</ListBoxItem>
</MySelect>
```

## Links

By default, interacting with an item in a Select triggers `onChange`. Alternatively, items may be links to another page or website. This can be achieved by passing the `href` prop to the `<ListBoxItem>` component. Link items in a `Select` are not selectable.

```tsx example
<MySelect label="Project">
  <ListBoxItem href="https://example.com/" target="_blank">Create new…</ListBoxItem>
  <ListBoxItem>Proposal</ListBoxItem>
  <ListBoxItem>Budget</ListBoxItem>
  <ListBoxItem>Onboarding</ListBoxItem>
</MySelect>
```

```css hidden
.react-aria-ListBoxItem[href] {
  text-decoration: none;
  cursor: pointer;
}
```

### Client side routing

The `<ListBoxItem>` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and [React Router](https://reactrouter.com/en/main). As with other React Aria components that support links, this works via the <TypeLink links={docs.links} type={docs.exports.RouterProvider} /> component at the root of your app. See the [client side routing guide](routing.html) to learn how to set this up.

## Sections

Select supports sections in order to group options. Sections can be used by wrapping groups of items in a `ListBoxSection` element. A `<Header>` element may also be included to label the section.

### Static items

```tsx example
import {ListBoxSection, Header} from 'react-aria-components';

<MySelect label="Preferred fruit or vegetable">
  <ListBoxSection>
    <Header>Fruit</Header>
    <ListBoxItem id="Apple">Apple</ListBoxItem>
    <ListBoxItem id="Banana">Banana</ListBoxItem>
    <ListBoxItem id="Orange">Orange</ListBoxItem>
    <ListBoxItem id="Honeydew">Honeydew</ListBoxItem>
    <ListBoxItem id="Grapes">Grapes</ListBoxItem>
    <ListBoxItem id="Watermelon">Watermelon</ListBoxItem>
    <ListBoxItem id="Cantaloupe">Cantaloupe</ListBoxItem>
    <ListBoxItem id="Pear">Pear</ListBoxItem>
  </ListBoxSection>
  <ListBoxSection>
    <Header>Vegetable</Header>
    <ListBoxItem id="Cabbage">Cabbage</ListBoxItem>
    <ListBoxItem id="Broccoli">Broccoli</ListBoxItem>
    <ListBoxItem id="Carrots">Carrots</ListBoxItem>
    <ListBoxItem id="Lettuce">Lettuce</ListBoxItem>
    <ListBoxItem id="Spinach">Spinach</ListBoxItem>
    <ListBoxItem id="Bok Choy">Bok Choy</ListBoxItem>
    <ListBoxItem id="Cauliflower">Cauliflower</ListBoxItem>
    <ListBoxItem id="Potatoes">Potatoes</ListBoxItem>
  </ListBoxSection>
</MySelect>
```

### Dynamic items

Sections used with dynamic items are populated from a hierarchical data structure. Similarly to the props on Select, `<ListBoxSection>` takes an array of data using the `items` prop. If the section also has a header,
the <TypeLink links={docs.links} type={docs.exports.Collection} /> component can be used to render the child items.

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

function Example() {
  let options = [
    {name: 'Fruit', children: [
      {name: 'Apple'},
      {name: 'Banana'},
      {name: 'Orange'},
      {name: 'Honeydew'},
      {name: 'Grapes'},
      {name: 'Watermelon'},
      {name: 'Cantaloupe'},
      {name: 'Pear'}
    ]},
    {name: 'Vegetable', children: [
      {name: 'Cabbage'},
      {name: 'Broccoli'},
      {name: 'Carrots'},
      {name: 'Lettuce'},
      {name: 'Spinach'},
      {name: 'Bok Choy'},
      {name: 'Cauliflower'},
      {name: 'Potatoes'}
    ]}
  ];

  return (
    <MySelect label="Preferred fruit or vegetable" items={options}>
      {section => (
        <ListBoxSection id={section.name}>
          <Header>{section.name}</Header>
          <Collection items={section.children}>
            {item => <ListBoxItem id={item.name}>{item.name}</ListBoxItem>}
          </Collection>
        </ListBoxSection>
      )}
    </MySelect>
  );
}
```

## Text slots

By default, items in a Select are labeled by their text contents for accessibility. ListBoxItems also support the "label" and "description" slots to separate primary and secondary content, which improves screen reader announcements and can also be used for styling purposes.

**Note**: The ARIA spec prohibits listbox items from including interactive content such as buttons, checkboxes, etc.

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

<MySelect label="Permissions">
  <ListBoxItem textValue="Read">
    <Text slot="label">Read</Text>
    <Text slot="description">Read only</Text>
  </ListBoxItem>
  <ListBoxItem textValue="Write">
    <Text slot="label">Write</Text>
    <Text slot="description">Read and write only</Text>
  </ListBoxItem>
  <ListBoxItem textValue="Admin">
    <Text slot="label">Admin</Text>
    <Text slot="description">Full access</Text>
  </ListBoxItem>
</MySelect>
```

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

```css
.react-aria-Select {
  .react-aria-SelectValue {
    [slot=description] {
      display: none;
    }
  }
}
```

</details>

## Asynchronous loading

This example uses the [useAsyncList](../react-stately/useAsyncList.html) hook to handle asynchronous loading
of data from a server. Use the [renderEmptyState](../react-aria/ListBox.html#empty-state) prop to display a spinner during initial load.
To enable infinite scrolling, render a [`<ListBoxLoadMoreItem>`](../react-aria/ListBox.html#listboxloadmoreitem) element at the end of the list.

```tsx example
import {Collection, ListBoxLoadMoreItem} from 'react-aria-components';
import {useAsyncList} from '@react-stately/data';

interface Character {
  name: string
}

function AsyncLoadingExample() {
  let list = useAsyncList<Character>({
    async load({signal, cursor, filterText}) {
      let res = await fetch(
        cursor || `https://pokeapi.co/api/v2/pokemon`,
        {signal}
      );
      let json = await res.json();

      return {
        items: json.results,
        cursor: json.next
      };
    }
  });

  return (
    <MySelect label="Pick a Pokemon">
      {/*- begin highlight -*/}
      <Collection items={list.items}>
        {(item) => (
          <ListBoxItem id={item.name}>{item.name}</ListBoxItem>
        )}
      </Collection>
      <ListBoxLoadMoreItem
        onLoadMore={list.loadMore}
        isLoading={list.loadingState === 'loadingMore'}>
        <MyProgressCircle isIndeterminate aria-label="Loading more..." />
      </ListBoxLoadMoreItem>
      {/*- end highlight -*/}
    </MySelect>
  );
}
```

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

```css
.react-aria-ListBoxLoadingIndicator {
  align-items: center;
  justify-content: center;
  height: 24px;
  width: 100%;
  display: flex;
}
```

</details>

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

```tsx example export=true render=false
import {ProgressBar} from 'react-aria-components';
import type {ProgressBarProps} from 'react-aria-components';

export function MyProgressCircle(props: ProgressBarProps) {
  return (
    <ProgressBar {...props}>
      <svg width="24" height="24" viewBox="0 0 24 24" style={{display: 'block'}}>
        <path fill="currentColor" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25" />
        <path fill="currentColor" d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z">
          <animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12" repeatCount="indefinite"/>
        </path>
      </svg>
    </ProgressBar>
  );
}
```

</details>

## Disabled

A Select can be fully disabled using the `isDisabled` prop.

```tsx example
<MySelect label="Choose frequency" isDisabled>
  <ListBoxItem id="rarely">Rarely</ListBoxItem>
  <ListBoxItem id="sometimes">Sometimes</ListBoxItem>
  <ListBoxItem id="always">Always</ListBoxItem>
</MySelect>
```

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

```css
.react-aria-Select {
  .react-aria-Button {
    &[data-disabled] {
      border-color: var(--border-color-disabled);
      color: var(--text-color-disabled);
      span[aria-hidden] {
        background: var(--border-color-disabled);
        color: var(--text-color-disabled);
      }

      .react-aria-SelectValue {
        &[data-placeholder] {
          color: var(--text-color-disabled);
        }
      }
    }
  }
}

@media (forced-colors: active) {
  .react-aria-Select {
    .react-aria-Button {
      &[data-disabled] span[aria-hidden] {
        background: 0 0;
      }
    }
  }
}
```

</details>

### Disabled options

`Select` supports marking items as disabled using the `disabledKeys` prop. Each key in this list
corresponds with the `id` prop passed to the `ListBoxItem` component, or automatically derived from the values passed
to the `items` prop. See the [Collections](collections.html) guide for more details.

Disabled items are not focusable, selectable, or keyboard navigable. The `isDisabled` property returned by
`useOption` can be used to style the item appropriately.

```tsx example
<MySelect label="Favorite Animal" disabledKeys={['cat', 'kangaroo']}>
  <ListBoxItem id="red panda">Red Panda</ListBoxItem>
  <ListBoxItem id="cat">Cat</ListBoxItem>
  <ListBoxItem id="dog">Dog</ListBoxItem>
  <ListBoxItem id="aardvark">Aardvark</ListBoxItem>
  <ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
  <ListBoxItem id="snake">Snake</ListBoxItem>
</MySelect>
```

## Validation

Select supports the `isRequired` prop to ensure the user selects an option, as well as custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more.

To display validation errors, add a `<FieldError>` element as a child of the Select. This allows you to render error messages from all of the above sources with consistent custom styles.

```tsx example
import {Form, FieldError} from 'react-aria-components';

<Form>
  {/*- begin highlight -*/}
  <Select name="animal" isRequired>
  {/*- end highlight -*/}
    <Label>Favorite Animal</Label>
    <Button>
      <SelectValue />
      <span aria-hidden="true">▼</span>
    </Button>
    {/*- begin highlight -*/}
    <FieldError />
    {/*- end highlight -*/}
    <Popover>
      <ListBox>
        <ListBoxItem>Aardvark</ListBoxItem>
        <ListBoxItem>Cat</ListBoxItem>
        <ListBoxItem>Dog</ListBoxItem>
        <ListBoxItem>Kangaroo</ListBoxItem>
        <ListBoxItem>Panda</ListBoxItem>
        <ListBoxItem>Snake</ListBoxItem>
      </ListBox>
    </Popover>
  </Select>
  <Button type="submit">Submit</Button>
</Form>
```

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

```css
.react-aria-Select {
  .react-aria-FieldError {
    font-size: 12px;
    color: var(--invalid-color);
  }
}
```

</details>

By default, `FieldError` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors.

### Description

The `description` slot can be used to associate additional help text with a Select.

```tsx example
<Select>
  <Label>Favorite Animal</Label>
  <Button>
    <SelectValue />
    <span aria-hidden="true"><ChevronDown size={16} /></span>
  </Button>
  {/*- begin highlight -*/}
  <Text slot="description">Please select an animal.</Text>
  {/*- end highlight -*/}
  <Popover>
    <ListBox>
      <ListBoxItem>Aardvark</ListBoxItem>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
      <ListBoxItem>Panda</ListBoxItem>
      <ListBoxItem>Snake</ListBoxItem>
    </ListBox>
  </Popover>
</Select>
```

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

```css
.react-aria-Select {
  [slot=description] {
    font-size: 12px;
  }
}
```

</details>

## Controlled open state

The open state of the select can be controlled via the `defaultOpen` and `isOpen` props

```tsx example
function Example() {
  let [open, setOpen] = React.useState(false);

  return (
    <>
      <p>Select is {open ? 'open' : 'closed'}</p>
      <MySelect label="Choose frequency" isOpen={open} onOpenChange={setOpen}>
        <ListBoxItem id="rarely">Rarely</ListBoxItem>
        <ListBoxItem id="sometimes">Sometimes</ListBoxItem>
        <ListBoxItem id="always">Always</ListBoxItem>
      </MySelect>
    </>
  );
}
```

## Customizing SelectValue

Select passes the rendered children of the selected item in the render props of the `SelectValue` as well as if the placeholder should be showing. You can use this to customize the value displayed in the Select.

```tsx example
<Select selectionMode="multiple">
  <Label>Favorite Animal</Label>
  <Button>
    {/*- begin highlight -*/}
    <SelectValue>
      {({selectedItems, defaultChildren, isPlaceholder}) => (
        isPlaceholder || selectedItems.length === 1 ? defaultChildren : `${selectedItems.length} selected items`
      )}
    </SelectValue>
    {/*- end highlight -*/}
    <span aria-hidden="true"><ChevronDown size={16} /></span>
  </Button>
  <Popover>
    <ListBox>
      <ListBoxItem>Aardvark</ListBoxItem>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
      <ListBoxItem>Panda</ListBoxItem>
      <ListBoxItem>Snake</ListBoxItem>
    </ListBox>
  </Popover>
</Select>
```

## Props

### Select

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

### Label

A `<Label>` accepts all HTML attributes.

### Button

A `<Button>` accepts its contents as `children`. Other props such as `onPress` and `isDisabled` will be set by the `Select`.

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

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

</details>

### SelectValue

The `<SelectValue>` component displays the current value of the select within the `<Button>`, or a placeholder if no value is selected.

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

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

</details>

### Popover

A `<Popover>` is a container to hold the `<ListBox>` suggestions for a Select. By default, it has a `placement` of `bottom start` within a `<Select>`, but this and other positioning properties may be customized.

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

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

</details>

### ListBox

Within a `<Select>`, most `<ListBox>` props are set automatically. The `<ListBox>` defines the options to display in a Select.

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

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

</details>

### ListBoxSection

A `<ListBoxSection>` defines the child items for a section within a `<ListBox>`. It may also contain an optional `<Header>` element. If there is no header, then an `aria-label` must be provided to identify the section to assistive technologies.

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

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

</details>

### Header

A `<Header>` defines the title for a `<ListBoxSection>`. It accepts all DOM attributes.

### ListBoxItem

A `<ListBoxItem>` defines a single option within a `<ListBox>`. If the `children` are not plain text, then the `textValue` prop must also be set to a plain text representation, which will be used for autocomplete in the Select.

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

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

</details>

### FieldError

A `<FieldError>` displays validation errors.

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

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

</details>

## 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-Select {
  /* ... */
}
```

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

```jsx
<Select className="my-select">
  {/* ... */}
</Select>
```

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

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

.react-aria-ListBoxItem[data-focused] {
  /* ... */
}
```

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
<ListBoxItem className={({isSelected}) => isSelected ? 'bg-blue-400' : 'bg-gray-100'}>
  Item
</ListBoxItem>
```

Render props may also be used as children to alter what elements are rendered based on the current state. For example, you could render a checkmark icon when an item is selected.

```jsx
<ListBoxItem>
  {({isSelected}) => (
    <>
      {isSelected && <CheckmarkIcon />}
      Item
    </>
  )}
</ListBoxItem>
```

The states and selectors for each component used in a `Select` are documented below.

### Select

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

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

### Label

A `Label` can be targeted with the `.react-aria-Label` CSS selector, or by overriding with a custom `className`.

### Button

A [Button](Button.html) can be targeted with the `.react-aria-Button` CSS selector, or by overriding with a custom `className`. It supports the following states:

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

### SelectValue

A `SelectValue` can be targeted with the `.react-aria-SelectValue` CSS selector, or by overriding with a custom `className`. It supports the following states and render props:

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

### Popover

The [Popover](Popover.html) component can be targeted with the `.react-aria-Popover` CSS selector, or by overriding with a custom `className`. Note that it renders in a [React Portal](https://reactjs.org/docs/portals.html), so it will not appear as a descendant of the Select in the DOM. It supports the following states and render props:

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

Within a Select, the popover will have the `data-trigger="Select"` attribute, which can be used to define select-specific styles. In addition, the `--trigger-width` CSS custom property will be set on the popover, which you can use to make the popover match the width of the select button.

```css render=false
.react-aria-Popover[data-trigger=Select] {
  width: var(--trigger-width);
}
```

### ListBox

A `ListBox` can be targeted with the `.react-aria-ListBox` CSS selector, or by overriding with a custom `className`.

### ListBoxSection

A `ListBoxSection` can be targeted with the `.react-aria-ListBoxSection` CSS selector, or by overriding with a custom `className`. See [sections](#sections) for examples.

### Header

A `Header` within a `ListBoxSection` can be targeted with the `.react-aria-Header` CSS selector, or by overriding with a custom `className`. See [sections](#sections) for examples.

### ListBoxItem

A `ListBoxItem` can be targeted with the `.react-aria-ListBoxItem` CSS selector, or by overriding with a custom `className`. It supports the following states and render props:

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

Items also support two slots: a label, and a description. When provided using the `<Text>` element, the item will have `aria-labelledby` and `aria-describedby` attributes pointing to these slots, improving screen reader announcement. See [text slots](#text-slots) for an example.

Note that items may not contain interactive children such as buttons, as screen readers will not be able to access them.

### Text

The help text elements within a `Select` can be targeted with the `[slot=description]` and `[slot=errorMessage]` CSS selectors, or by adding a custom `className`.

### FieldError

A `FieldError` can be targeted with the `.react-aria-FieldError` CSS selector, or by overriding with a custom `className`. It supports the following render props:

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

## Advanced customization

### Composition

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

```tsx
function MyListBox(props) {
  return <ListBox {...props} className="my-listbox" />
}
```

### 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={['Select']} docs={docs} />

This example shows a `FieldGroup` component that renders a group of selects with a title. The entire group can be marked as disabled via the `isDisabled` prop, which is passed to all child selects via the `SelectContext` provider.

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

interface FieldGroupProps {
  title?: string,
  children?: React.ReactNode,
  isDisabled?: boolean
}

function FieldGroup({title, children, isDisabled}: FieldGroupProps) {
  return (
    <fieldset>
      <legend>{title}</legend>
      {/*- begin highlight -*/}
      <SelectContext.Provider value={{isDisabled}}>
      {/*- end highlight -*/}
        {children}
      </SelectContext.Provider>
    </fieldset>
  );
}

<FieldGroup title="Filters" isDisabled>
  <MySelect label="Status" defaultValue="published">
    <ListBoxItem id="draft">Draft</ListBoxItem>
    <ListBoxItem id="published">Published</ListBoxItem>
    <ListBoxItem id="deleted">Deleted</ListBoxItem>
  </MySelect>
  <MySelect label="Author" defaultValue="emma">
    <ListBoxItem id="john">John</ListBoxItem>
    <ListBoxItem id="emma">Emma</ListBoxItem>
    <ListBoxItem id="tim">Tim</ListBoxItem>
  </MySelect>
</FieldGroup>
```

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

```css
fieldset {
  padding: 1.5em;
  width: fit-content;
}
```

</details>

### Custom children

Select passes props to its child components, such as the label and popover, via their associated contexts. These contexts are exported so you can also consume them in your own custom components. This enables you to reuse existing components from your app or component library together with React Aria Components.

<ContextTable components={['Label', 'Button', 'Popover', 'ListBox', 'Text']} docs={docs} />

This example consumes from `LabelContext` in an existing styled label component to make it compatible with React Aria Components. The <TypeLink links={docs.links} type={docs.exports.useContextProps} /> hook merges the local props and ref with the ones provided via context by Select.

```tsx
import type {LabelProps} from 'react-aria-components';
import {LabelContext, useContextProps} from 'react-aria-components';

const MyCustomLabel = React.forwardRef((props: LabelProps, ref: React.ForwardedRef<HTMLLabelElement>) => {
  // Merge the local props and ref with the ones provided via context.
  ///- begin highlight -///
  [props, ref] = useContextProps(props, ref, LabelContext);
  ///- end highlight -///

  // ... your existing Label component
  return <label {...props} ref={ref} />;
});
```

Now you can use `MyCustomLabel` within a `Select`, in place of the builtin React Aria Components `Label`.

```tsx
<Select>
  {/*- begin highlight -*/}
  <MyCustomLabel>Name</MyCustomLabel>
  {/*- end highlight -*/}
  {/* ... */}
</Select>
```

### State

Select provides an <TypeLink links={statelyDocs.links} type={statelyDocs.exports.SelectState} /> object to its children via `SelectStateContext`. This can be used to access and manipulate the select's state.

This example shows a `SelectClearButton` component that can be placed within a `Select` to allow the user to clear the selected item.

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

function SelectClearButton() {
  /*- begin highlight -*/
  let state = React.useContext(SelectStateContext);
  /*- end highlight -*/
  return (
    <Button
      // Don't inherit behavior from Select.
      slot={null}
      style={{fontSize: 'small', marginTop: 6, padding: 4}}
      onPress={() => state?.setValue(null)}>
      Clear
    </Button>
  );
}

<Select>
  <Label>Favorite Animal</Label>
  <Button>
    <SelectValue />
    <span aria-hidden="true"><ChevronDown size={16} /></span>
  </Button>
  {/*- begin highlight -*/}
  <SelectClearButton />
  {/*- end highlight -*/}
  <Popover>
    <ListBox>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
    </ListBox>
  </Popover>
</Select>
```

### Hooks

If you need to customize things even further, such as accessing internal state, intercepting events, or customizing the DOM structure, you can drop down to the lower level Hook-based API. See [useSelect](useSelect.html) for more details.

## Accessibility

### False positives

Select may trigger a [known accessibility false positive](https://github.com/adobe/react-spectrum/wiki/Known-accessibility-false-positives#picker)
from automated accessibility testing tools. This is because we include a visually hidden select element alongside the Select to specifically aid with browser form autocomplete
and hide it from screen readers via `aria-hidden` since users don't need to interact with the hidden select. We manage focus internally
so that focusing this hidden select will always shift focus to the Select's trigger button instead. Automated accessibility testing tools have no way of
knowing that we manage the focus in this way and thus throw this false positive.

To facilitate the suppression of this false positive, the `data-a11y-ignore="aria-hidden-focus"` data attribute is automatically applied to the
problematic element and references the relevant `AXE` rule. Please use this data attribute to target the problematic element and exclude it
from your automated accessibility tests as shown [here](./accessibility.html#false-positives).

## Testing

### Test utils <VersionBadge version="beta" style={{marginLeft: 4, verticalAlign: 'bottom'}} />

`@react-aria/test-utils` offers common select interaction utilities which you may find helpful when writing tests. See [here](./testing.html#react-aria-test-utils) for more information on how to setup these utilities
in your tests. Below is the full definition of the select tester and a sample of how you could use it in your test suite.

```ts
// Select.test.ts
import {render} from '@testing-library/react';
import {User} from '@react-aria/test-utils';

let testUtilUser = new User({interactionType: 'mouse'});
// ...

it('Select can select an option via keyboard', async function () {
  // Render your test component/app and initialize the select tester
  let {getByTestId} = render(
    <Select data-testid="test-select">
     ...
    </Select>
  );
  let selectTester = testUtilUser.createTester('Select', {root: getByTestId('test-select'), interactionType: 'keyboard'});
  let trigger = selectTester.trigger;
  expect(trigger).toHaveTextContent('Select an item');

  await selectTester.selectOption({option: 'Cat'});
  expect(trigger).toHaveTextContent('Cat');
});
```

<ClassAPI links={selectUtil.links} class={selectUtil.exports.SelectTester} />
