> For AI agents: the complete documentation index is available at https://wallarm.github.io/design-system/llms.txt, the full documentation bundle is available at https://wallarm.github.io/design-system/llms-full.txt.

# Select

Holds one answer, or several, chosen from a list — below about six options expose them instead with `Radio` or `SegmentedControl`, and reach for `DropdownMenu` when the items run commands rather than set a value. The trigger is composed rather than configured: `SelectButton` for a button-shaped trigger, `SelectInput` for one that looks like a field.

[Source](https://github.com/wallarm/design-system/tree/main/packages/design-system/src/components/Select) · [Storybook](https://wallarm.github.io/design-system/storybook/?path=/docs/inputs-select--overview)

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const Basic = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
    isItemDisabled: item => item.value === 'angular',
  });

  return (
    <div className='w-300'>
      <Select collection={collection} data-testid='select'>
        <SelectButton />

        <SelectPositioner>
          <SelectContent>
            {collection.items.map(skill => (
              <SelectOption key={skill.value} item={skill}>
                <SelectOptionText>{skill.label}</SelectOptionText>
                <SelectOptionIndicator />
              </SelectOption>
            ))}
          </SelectContent>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

## Usage

```tsx
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
```

## Examples

### Sizes

The same height scale as the other fields, so a select sits in a row of inputs without
breaking the line.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectInput, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { HStack, VStack } from '@wallarm-org/design-system/Stack';

export const Sizes = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
  });

  return (
    <VStack gap={16} align='stretch'>
      <HStack gap={16} align='start'>
        <Select collection={collection}>
          <SelectButton size='default' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection}>
          <SelectButton size='medium' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection}>
          <SelectButton size='small' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </HStack>

      <HStack gap={16} align='start'>
        <Select collection={collection}>
          <SelectInput size='default' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection}>
          <SelectInput size='medium' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection}>
          <SelectInput size='small' />
          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </HStack>
    </VStack>
  );
};
```

### Different buttons

The trigger is yours to shape — labelled, icon-led, or value-only. Whatever it looks like,
it must still read as something that opens.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { HStack, VStack } from '@wallarm-org/design-system/Stack';

export const DifferentButtons = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
  });

  return (
    <div className='w-800'>
      <VStack gap={16}>
        <HStack gap={8}>
          <Select collection={collection}>
            <SelectButton placeholder='Default' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection}>
            <SelectButton variant='ghost' placeholder='Ghost + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection}>
            <SelectButton variant='ghost' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection}>
            <SelectButton variant='secondary' placeholder='Secondary + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection}>
            <SelectButton variant='secondary' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>
        </HStack>

        <HStack gap={8}>
          <Select collection={collection} disabled>
            <SelectButton placeholder='Default' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} disabled>
            <SelectButton variant='ghost' placeholder='Ghost + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} disabled>
            <SelectButton variant='ghost' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} disabled>
            <SelectButton variant='secondary' placeholder='Secondary + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} disabled>
            <SelectButton variant='secondary' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>
        </HStack>

        <HStack gap={8}>
          <Select collection={collection} loading>
            <SelectButton placeholder='Default' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} loading>
            <SelectButton variant='ghost' placeholder='Ghost + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} loading>
            <SelectButton variant='ghost' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} loading>
            <SelectButton variant='secondary' placeholder='Secondary + Neutral' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>

          <Select collection={collection} loading>
            <SelectButton variant='secondary' color='brand' placeholder='Ghost + Brand' />

            <SelectPositioner>
              <SelectContent>
                {collection.items.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>
        </HStack>
      </VStack>
    </div>
  );
};
```

### Multiple

`multiple` collects several answers, and the trigger summarises them. Once past a couple of
selections a summary beats a list, which is what `WithTags` is for.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectContent, SelectInput, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { VStack } from '@wallarm-org/design-system/Stack';

export const Multiple = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
  });

  return (
    <VStack>
      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>

      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          invalid
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>

      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          disabled
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>
    </VStack>
  );
};
```

### Multiple with icons

Icons carry the option's identity into the closed trigger, which matters more in a
multi-select where the text is compressed into a summary.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectContent, SelectInput, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { VStack } from '@wallarm-org/design-system/Stack';

export const MultipleWithIcons = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <VStack>
      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => {
                const { icon: Icon } = skill;

                return (
                  <SelectOption key={skill.value} item={skill}>
                    {Icon && <Icon />}
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                );
              })}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>

      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          invalid
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => {
                const { icon: Icon } = skill;

                return (
                  <SelectOption key={skill.value} item={skill}>
                    {Icon && <Icon />}
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                );
              })}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>

      <div className='w-400'>
        <Select
          collection={collection}
          multiple
          disabled
          defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
        >
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => {
                const { icon: Icon } = skill;

                return (
                  <SelectOption key={skill.value} item={skill}>
                    {Icon && <Icon />}
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                );
              })}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </div>
    </VStack>
  );
};
```

### Grouped

`SelectGroup` with `SelectGroupLabel` splits a long list into named sections. Group when
the reader would otherwise scan, not merely because the options have categories.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectClearTrigger, SelectContent, SelectGroup, SelectGroupLabel, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const Grouped = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
    groupBy: item => item.category ?? '',
  });

  return (
    <Select collection={collection}>
      <SelectButton />

      <SelectPositioner>
        <SelectContent>
          {collection.group().map(([category, group], index) => (
            <SelectGroup key={category}>
              <SelectGroupLabel>
                {category}
                {index === 0 && <SelectClearTrigger>Clear all</SelectClearTrigger>}
              </SelectGroupLabel>
              {group.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectGroup>
          ))}
        </SelectContent>
      </SelectPositioner>
    </Select>
  );
};
```

### Disabled

The whole control is out, trigger included. Disabling individual options instead keeps the
list honest about what exists.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const Disabled = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <Select collection={collection} disabled>
      <SelectButton />

      <SelectPositioner>
        <SelectContent>
          {collection.items.map(skill => (
            <SelectOption key={skill.value} item={skill}>
              <SelectOptionText>{skill.label}</SelectOptionText>
              <SelectOptionIndicator />
            </SelectOption>
          ))}
        </SelectContent>
      </SelectPositioner>
    </Select>
  );
};
```

### Loading

`loading` on the root, for a list still being fetched. It holds the trigger's shape so the
layout doesn't jump when the options land.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const Loading = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <Select collection={collection} loading>
      <SelectButton />

      <SelectPositioner>
        <SelectContent>
          {collection.items.map(skill => (
            <SelectOption key={skill.value} item={skill}>
              <SelectOptionText>{skill.label}</SelectOptionText>
              <SelectOptionIndicator />
            </SelectOption>
          ))}
        </SelectContent>
      </SelectPositioner>
    </Select>
  );
};
```

### With select input

`SelectInput` makes the trigger look like a text field, which suits a select sitting in a
form beside real inputs rather than in a toolbar.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectContent, SelectInput, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { VStack } from '@wallarm-org/design-system/Stack';

export const WithSelectInput = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <div className='w-300'>
      <VStack align='stretch'>
        <Select collection={collection}>
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection} invalid>
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>

        <Select collection={collection} disabled>
          <SelectInput />

          <SelectPositioner>
            <SelectContent>
              {collection.items.map(skill => (
                <SelectOption key={skill.value} item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>
              ))}
            </SelectContent>
          </SelectPositioner>
        </Select>
      </VStack>
    </div>
  );
};
```

### With separator

`SelectSeparator` divides kinds of option — a destructive or clear-all entry from the real
choices — where a group label would be overkill.

```tsx
import { Fragment } from 'react';
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSeparator } from '@wallarm-org/design-system/Select';

export const WithSeparator = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <div className='w-300'>
      <Select collection={collection}>
        <SelectButton />

        <SelectPositioner>
          <SelectContent>
            {collection.items.map((skill, index) => (
              <Fragment key={skill.value}>
                <SelectOption item={skill}>
                  <SelectOptionText>{skill.label}</SelectOptionText>
                  <SelectOptionIndicator />
                </SelectOption>

                {index === 3 && <SelectSeparator />}
              </Fragment>
            ))}
          </SelectContent>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

### With icons

`SelectValueIcon` in the option and the trigger, so the chosen option keeps its icon once
the menu closes.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const WithIcons = () => {
  const collection = createListCollection({
    items: skills,
  });

  return (
    <div className='w-300'>
      <Select collection={collection}>
        <SelectButton />

        <SelectPositioner>
          <SelectContent>
            {collection.items.map(({ icon: Icon, ...skill }) => (
              <SelectOption key={skill.value} item={skill}>
                {Icon && <Icon />}
                <SelectOptionText>{skill.label}</SelectOptionText>
                <SelectOptionIndicator />
              </SelectOption>
            ))}
          </SelectContent>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

### With footer

`SelectFooter` pins content below the scrolling list, for a persistent escape like managing
the options themselves.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Button } from '@wallarm-org/design-system/Button';
import { SquareArrowOutUpRight } from '@wallarm-org/design-system/icons';
import { Select, SelectButton, SelectClearTrigger, SelectContent, SelectFooter, SelectGroup, SelectGroupLabel, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { HStack } from '@wallarm-org/design-system/Stack';

export const WithFooter = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
    groupBy: item => item.category ?? '',
  });

  return (
    <div className='w-300'>
      <Select collection={collection}>
        <SelectButton />

        <SelectPositioner>
          <SelectContent>
            {collection.group().map(([category, group], index) => (
              <SelectGroup key={category}>
                <SelectGroupLabel>
                  {category}
                  {index === 0 && <SelectClearTrigger>Clear all</SelectClearTrigger>}
                </SelectGroupLabel>
                {group.map(skill => (
                  <SelectOption key={skill.value} item={skill}>
                    <SelectOptionText>{skill.label}</SelectOptionText>
                    {skill.description && (
                      <SelectOptionDescription>{skill.description}</SelectOptionDescription>
                    )}
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectGroup>
            ))}
          </SelectContent>

          <SelectFooter>
            <HStack justify='between'>
              <Button variant='ghost' color='neutral' size='small'>
                <SquareArrowOutUpRight />
                See all
              </Button>

              <HStack justify='end'>
                <Button variant='ghost' color='neutral' size='small'>
                  Cancel
                </Button>

                <Button variant='primary' color='brand' size='small'>
                  Apply
                </Button>
              </HStack>
            </HStack>
          </SelectFooter>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

### With search

`SelectSearchInput` with the `useSelectSearch` hook, plus `SelectEmptyState` for when
nothing matches. Add search once the list outgrows a glance — roughly ten options.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Button } from '@wallarm-org/design-system/Button';
import { SquareArrowOutUpRight } from '@wallarm-org/design-system/icons';
import { Select, SelectButton, SelectClearTrigger, SelectContent, SelectEmptyState, SelectFooter, SelectGroup, SelectGroupLabel, SelectHeader, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSearchInput, useSelectSearch } from '@wallarm-org/design-system/Select';
import { HStack } from '@wallarm-org/design-system/Stack';

export const WithSearch = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
    groupBy: item => item.category ?? '',
    itemToString: item => item.label,
  });

  const { searchValue, onSearchChange, filteredCollection } = useSelectSearch(collection);

  return (
    <div className='w-300'>
      <Select collection={collection}>
        <SelectButton />

        <SelectPositioner>
          <SelectHeader>
            <SelectSearchInput value={searchValue} onChange={onSearchChange} />
          </SelectHeader>

          <SelectContent>
            {filteredCollection.size === 0 ? (
              <SelectEmptyState description={`No results for "${searchValue}"`} />
            ) : (
              filteredCollection.group().map(([category, group], index) => (
                <SelectGroup key={category}>
                  <SelectGroupLabel>
                    {category}
                    {index === 0 && <SelectClearTrigger>Clear all</SelectClearTrigger>}
                  </SelectGroupLabel>
                  {group.map(skill => (
                    <SelectOption key={skill.value} item={skill}>
                      <SelectOptionText>{skill.label}</SelectOptionText>
                      {skill.description && (
                        <SelectOptionDescription>{skill.description}</SelectOptionDescription>
                      )}
                      <SelectOptionIndicator />
                    </SelectOption>
                  ))}
                </SelectGroup>
              ))
            )}
          </SelectContent>

          <SelectFooter>
            <HStack justify='between'>
              <Button variant='ghost' color='neutral' size='small'>
                <SquareArrowOutUpRight />
                See all
              </Button>

              <HStack justify='end'>
                <Button variant='ghost' color='neutral' size='small'>
                  Cancel
                </Button>

                <Button variant='primary' color='brand' size='small'>
                  Apply
                </Button>
              </HStack>
            </HStack>
          </SelectFooter>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

### With form field

Inside `Field`, so the label and description come from `FieldLabel` and `FieldDescription`
rather than from the select.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Field, FieldContent, FieldLabel, FieldSet } from '@wallarm-org/design-system/Field';
import { Select, SelectButton, SelectContent, SelectInput, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';

export const WithFormField = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
  });

  return (
    <div className='w-300'>
      <FieldSet>
        <Field>
          <FieldLabel>Single with SelectInput</FieldLabel>
          <FieldContent>
            <Select collection={collection}>
              <SelectInput />

              <SelectPositioner>
                <SelectContent>
                  {collection.items.map(skill => (
                    <SelectOption key={skill.value} item={skill}>
                      <SelectOptionText>{skill.label}</SelectOptionText>
                      <SelectOptionIndicator />
                    </SelectOption>
                  ))}
                </SelectContent>
              </SelectPositioner>
            </Select>
          </FieldContent>
        </Field>

        <Field>
          <FieldLabel>Single with SelectButton</FieldLabel>
          <FieldContent>
            <Select collection={collection} defaultValue={['react']}>
              <SelectButton />

              <SelectPositioner>
                <SelectContent>
                  {collection.items.map(skill => (
                    <SelectOption key={skill.value} item={skill}>
                      <SelectOptionText>{skill.label}</SelectOptionText>
                      <SelectOptionIndicator />
                    </SelectOption>
                  ))}
                </SelectContent>
              </SelectPositioner>
            </Select>
          </FieldContent>
        </Field>

        <Field>
          <FieldLabel>Multiple with SelectInput</FieldLabel>
          <FieldContent>
            <Select collection={collection} multiple defaultValue={['react', 'vue']}>
              <SelectInput />

              <SelectPositioner>
                <SelectContent>
                  {collection.items.map(skill => (
                    <SelectOption key={skill.value} item={skill}>
                      <SelectOptionText>{skill.label}</SelectOptionText>
                      <SelectOptionIndicator />
                    </SelectOption>
                  ))}
                </SelectContent>
              </SelectPositioner>
            </Select>
          </FieldContent>
        </Field>

        <Field>
          <FieldLabel>Multiple with SelectButton</FieldLabel>
          <FieldContent>
            <Select collection={collection} multiple defaultValue={['react', 'vue', 'angular']}>
              <SelectButton />

              <SelectPositioner>
                <SelectContent>
                  {collection.items.map(skill => (
                    <SelectOption key={skill.value} item={skill}>
                      <SelectOptionText>{skill.label}</SelectOptionText>
                      <SelectOptionIndicator />
                    </SelectOption>
                  ))}
                </SelectContent>
              </SelectPositioner>
            </Select>
          </FieldContent>
        </Field>
      </FieldSet>
    </div>
  );
};
```

### With tags

Selections render as removable tags inside the field, which is the honest shape for
multi-select when the reader needs to see and undo each choice individually.

```tsx
import { createListCollection } from '@ark-ui/react/collection';
import { Select, SelectContent, SelectInput, SelectOption, SelectPositioner } from '@wallarm-org/design-system/Select';
import { Tag } from '@wallarm-org/design-system/Tag';

export const WithTags = () => {
  const collection = createListCollection({
    items: skillsWithoutIcons,
  });

  return (
    <div className='w-300'>
      <Select
        collection={collection}
        multiple
        defaultValue={['react', 'vue', 'angular', 'nodejs', 'python', 'java', 'typescript']}
      >
        <SelectInput />

        <SelectPositioner>
          <SelectContent>
            {collection.items.map(skill => (
              <SelectOption key={skill.value} item={skill}>
                <Tag>{skill.label}</Tag>
              </SelectOption>
            ))}
          </SelectContent>
        </SelectPositioner>
      </Select>
    </div>
  );
};
```

## Props

| Prop                    | Type                                                      | Default | Description                                                                                                                                                                                                |
| ----------------------- | --------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| form                    | `string \| undefined`                                     |         | The associate form of the underlying select.                                                                                                                                                               |
| title                   | `string \| undefined`                                     |         |                                                                                                                                                                                                            |
| defaultChecked          | `boolean \| undefined`                                    |         |                                                                                                                                                                                                            |
| defaultValue            | `string[] \| undefined`                                   |         | The initial default value of the select when rendered. Use when you don't need to control the value of the select.                                                                                         |
| autoFocus               | `boolean \| undefined`                                    |         |                                                                                                                                                                                                            |
| id                      | `string`                                                  |         | The unique identifier of the machine.                                                                                                                                                                      |
| tabIndex                | `number \| undefined`                                     |         |                                                                                                                                                                                                            |
| rel                     | `string \| undefined`                                     |         |                                                                                                                                                                                                            |
| onChange                | `ChangeEventHandler<T, Element> \| undefined`             |         |                                                                                                                                                                                                            |
| onSelect                | `((details: SelectionDetails) => void) \| undefined`      |         | Function called when an item is selected                                                                                                                                                                   |
| disabled                | `boolean \| undefined`                                    | `false` | Whether the select is disabled                                                                                                                                                                             |
| name                    | `string \| undefined`                                     |         | The `name` attribute of the underlying select.                                                                                                                                                             |
| value                   | `string[] \| undefined`                                   |         | The controlled keys of the selected items                                                                                                                                                                  |
| asChild                 | `boolean \| undefined`                                    |         | Use the provided child element as the default rendered element, combining their props and behavior.                                                                                                        |
| ids                     | `ElementIds \| undefined`                                 |         | The ids of the elements in the select. Useful for composition.                                                                                                                                             |
| defaultHighlightedValue | `string \| null \| undefined`                             |         | The initial value of the highlighted item when opened. Use when you don't need to control the highlighted value of the select.                                                                             |
| highlightedValue        | `string \| null \| undefined`                             |         | The controlled key of the highlighted item                                                                                                                                                                 |
| onHighlightChange       | `complex`                                                 |         | The callback fired when the highlighted item changes.                                                                                                                                                      |
| loopFocus               | `boolean \| undefined`                                    |         | Whether to loop the keyboard navigation through the options                                                                                                                                                |
| closeOnSelect           | `boolean \| undefined`                                    |         | Whether the select should close after an item is selected                                                                                                                                                  |
| open                    | `boolean \| undefined`                                    |         | Whether the select menu is open                                                                                                                                                                            |
| onOpenChange            | `((details: OpenChangeDetails) => void) \| undefined`     |         | Function called when the popup is opened                                                                                                                                                                   |
| defaultOpen             | `boolean \| undefined`                                    |         | Whether the select's open state is controlled by the user                                                                                                                                                  |
| composite               | `boolean \| undefined`                                    |         | Whether the select is a composed with other composite widgets like tabs or combobox                                                                                                                        |
| onPointerDownOutside    | `complex`                                                 |         | Function called when the pointer is pressed down outside the component                                                                                                                                     |
| onFocusOutside          | `complex`                                                 |         | Function called when the focus is moved outside the component                                                                                                                                              |
| onInteractOutside       | `complex`                                                 |         | Function called when an interaction happens outside the component                                                                                                                                          |
| present                 | `boolean \| undefined`                                    |         | Whether the node is present (controlled by the user)                                                                                                                                                       |
| onExitComplete          | `VoidFunction \| undefined`                               |         | Function called when the animation ends in the closed state                                                                                                                                                |
| onEnterComplete         | `VoidFunction \| undefined`                               |         | Function called when the animation ends in the open state                                                                                                                                                  |
| immediate               | `boolean \| undefined`                                    |         | Whether to synchronize the present change immediately or defer it to the next frame                                                                                                                        |
| autoComplete            | `string \| undefined`                                     |         | The autocomplete attribute for the hidden select. Enables browser autofill (e.g. "address-level1" for state).                                                                                              |
| readOnly                | `boolean \| undefined`                                    |         | Whether the select is read-only                                                                                                                                                                            |
| required                | `boolean \| undefined`                                    |         | Whether the select is required                                                                                                                                                                             |
| invalid                 | `boolean \| undefined`                                    |         | Whether the select is invalid                                                                                                                                                                              |
| onValueChange           | `((details: ValueChangeDetails<T>) => void) \| undefined` |         | The callback fired when the selected item changes.                                                                                                                                                         |
| multiple                | `boolean \| undefined`                                    |         | Whether to allow multiple selection                                                                                                                                                                        |
| collection \*           | `ListCollection<T>`                                       |         | The collection of items                                                                                                                                                                                    |
| translations            | `IntlTranslations \| undefined`                           |         | Specifies the localized strings that identifies the accessibility elements and their states                                                                                                                |
| scrollToIndexFn         | `((details: ScrollToIndexDetails) => void) \| undefined`  |         | Function to scroll to a specific index                                                                                                                                                                     |
| deselectable            | `boolean \| undefined`                                    |         | Whether the value can be cleared by clicking the selected item. **Note:** this is only applicable for single selection                                                                                     |
| skipAnimationOnMount    | `boolean \| undefined`                                    |         | Whether to allow the initial presence animation.                                                                                                                                                           |
| hideMode                | `"display-none" \| "activity"`                            |         | How to hide content when mounted but not present. - `'display-none'`: HTML `hidden` attribute. Effects stay alive. - `'activity'`: React 19 `<Activity mode="hidden">`. Effects pause. Requires React 19+. |
| loading                 | `boolean \| undefined`                                    | `false` |                                                                                                                                                                                                            |
| positioning             | `PositioningOptions \| undefined`                         |         | Override default floating positioning (merged with DS defaults).                                                                                                                                           |
| data-testid             | `string \| undefined`                                     |         |                                                                                                                                                                                                            |

### SelectEmptyState

| Prop        | Type        | Default      | Description |
| ----------- | ----------- | ------------ | ----------- |
| description | `ReactNode` | `No results` |             |

### SelectFooter

| Prop           | Type                                                 | Default   | Description |
| -------------- | ---------------------------------------------------- | --------- | ----------- |
| title          | `string \| undefined`                                |           |             |
| defaultChecked | `boolean \| undefined`                               |           |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |           |             |
| autoFocus      | `boolean \| undefined`                               |           |             |
| id             | `string \| undefined`                                |           |             |
| tabIndex       | `number \| undefined`                                |           |             |
| rel            | `string \| undefined`                                |           |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |           |             |
| variant        | `{ default: string; actions: string; }`              | `default` |             |
| data-testid    | `string \| undefined`                                |           |             |

### SelectOptionHint

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### SelectPositioner

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                                                                |
| -------------- | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| contentProps   | `complex`                                            |         | Props for the content element (the `listbox` panel inside the positioner) — for a ref, an inline measurement such as a locked width, or `data-*` attributes. `className` on the positioner itself already lands on the content, and overrides its default sizes (`min-w-240 max-w-320 max-h-(--available-height)`) through tailwind-merge. |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                            |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                            |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                                                                            |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                            |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                            |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                            |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                            |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                                                                            |
| asChild        | `boolean \| undefined`                               |         | Use the provided child element as the default rendered element, combining their props and behavior.                                                                                                                                                                                                                                        |

### SelectSearchInput

| Prop           | Type                                                 | Default | Description                                                                     |
| -------------- | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------- |
| value \*       | `string`                                             |         |                                                                                 |
| onChange \*    | `(value: string) => void`                            |         |                                                                                 |
| onClear        | `(() => void) \| undefined`                          |         | Called when the built-in clear button empties the field, before `onChange('')`. |
| title          | `string \| undefined`                                |         |                                                                                 |
| pattern        | `string \| undefined`                                |         |                                                                                 |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                 |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                 |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                 |
| id             | `string \| undefined`                                |         |                                                                                 |
| tabIndex       | `number \| undefined`                                |         |                                                                                 |
| rel            | `string \| undefined`                                |         |                                                                                 |
| disabled       | `boolean \| undefined`                               |         |                                                                                 |
| name           | `string \| undefined`                                |         |                                                                                 |
| alt            | `string \| undefined`                                |         |                                                                                 |
| height         | `string \| number \| undefined`                      |         |                                                                                 |
| src            | `string \| undefined`                                |         |                                                                                 |
| width          | `string \| number \| undefined`                      |         |                                                                                 |
| autoComplete   | `HTMLInputAutoCompleteAttribute \| undefined`        |         |                                                                                 |
| maxLength      | `number \| undefined`                                |         |                                                                                 |
| minLength      | `number \| undefined`                                |         |                                                                                 |
| placeholder    | `string \| undefined`                                |         |                                                                                 |
| readOnly       | `boolean \| undefined`                               |         |                                                                                 |
| required       | `boolean \| undefined`                               |         |                                                                                 |
| checked        | `boolean \| undefined`                               |         |                                                                                 |
| step           | `string \| number \| undefined`                      |         |                                                                                 |
| accept         | `string \| undefined`                                |         |                                                                                 |
| max            | `string \| number \| undefined`                      |         |                                                                                 |
| min            | `string \| number \| undefined`                      |         |                                                                                 |
| multiple       | `boolean \| undefined`                               |         |                                                                                 |
| data-testid    | `string \| undefined`                                |         |                                                                                 |

### SelectSeparator

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

## Explorer

