A multi-select asks for a set rather than a value, so it reports in two places: the trigger
counts what is held, and the chips below it name each choice and offer to remove it. It
shares the dropdown's menu, search, keyboard navigation, disabled options, and differs by
accepting a list, never closing on a choice, and keeping the selection visible after the
menu is gone.

```tsx demo="forms/multi-select-preview"
```

## Usage

```tsx
import { MultiSelect } from "@asheeui/web";

const topics = [
  { label: "Invoices", value: "invoices" },
  { label: "Payments", value: "payments" },
];

<MultiSelect
  label="Topics you follow"
  InputLabel="Choose topics..."
  options={topics}
  value={values}
  onChange={setValues}
/>
```

Two props say what the field is called. `label` is the field's label, above the control, and
`InputLabel` is the trigger's empty text, shown while nothing is selected, it defaults to
`"Select options"`, so state it. A `value` array controls the selection; without one the
component keeps the accumulated selection itself and still reports every change through
`onChange`.

Choosing an option toggles it, and the menu stays open, so a set is built in one visit
rather than one visit per option.

## Selection and chips

The chips are derived from `value`, so by default they cannot disagree with the selection.
`chipLabel` puts a caption above them, and `disableChipDisplay` hides the panel entirely
while the trigger keeps counting, which suits a field whose chips would crowd the form. Chip
appearance comes from the `chip` bag: `color`, `size`, `radius` and a `className` override.
Its size is registered as `sm`, its colour falls back to the trigger's resolved colour, and
its radius to the trigger's radius and then `sm`.

When the selection is owned elsewhere, a table's filter store, a wizard, `chipOptions`
replaces the derived chips and `handleAddChip` and `handleRemoveChip` replace the toggle, so
the component draws what it is given instead of deciding.

Search is on by default here, unlike the dropdown: `isSearch` adds the field at the top of
the menu, `searchPlaceholder` and `searchInputName` name it, and `belowList` renders under
the options.

```tsx demo="forms/multi-select-chips"
```

## Props

```props MultiSelect
```

The trigger follows the field family's web defaults, `size` is `md` and `variant` is
`bordered`, while `radius` follows the application's `defaultRadius` and `color` its
`defaultColor`. A `status` of `error` outranks that colour with the semantic `danger` role
and sets `aria-invalid`, which is the family's rule rather than this component's.

The chip bag resolves separately: `chip.size` is registered `sm`, `chip.color` falls back to
the resolved trigger colour, and `chip.radius` to the trigger's radius and then `sm`. Write
them under `components.multiSelect.chip` to change them once, or in the `chip` prop to
change them for one instance.

## Accessibility

- The trigger is a real `<button type="button">` with `aria-haspopup="listbox"` and
  `aria-expanded`, named by the field's label. The description and message are referenced
  with `aria-describedby`, and an `error` status sets `aria-invalid`.
- The list is a `role="listbox"` carrying `aria-multiselectable`, and each option is a
  `role="option"` with `aria-selected`. Choosing one toggles it without closing the menu, so
  a keyboard user can build the whole set before <kbd>Escape</kbd> closes it and returns
  focus to the trigger.
- Keyboard navigation is the menu's: <kbd>↑</kbd> and <kbd>↓</kbd> move the current option
  and wrap, <kbd>Home</kbd> and <kbd>End</kbd> jump to the edges, typed characters jump to
  the first option whose label starts with them, and the search field filters the list as
  you type.
- Each chip's remove control is a real button whose accessible name is "Remove" followed by
  the option's label, so a chip can be removed without a pointer; while the field is
  disabled those controls leave the tab order with it.

The label, description and message behave as the [field anatomy](/concepts/fields) describes.

## Related

```related dropmenu, radio, form
```
