A dropdown asks for one value out of a set that is too long to keep on the page. What
separates it from a radio group is not the number of options but their cost, because the
list stays out of the way until it is asked for, and it can be searched, styled apart from
the trigger and rendered over the page's clipping. The trigger is a `Button`, so it takes
the button's variants, sizes and colours, and the field around it is the field family's
label, description and message.

```tsx demo="forms/dropmenu-preview"
```

## Usage

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

const speeds = [
  { label: "Standard", value: "standard" },
  { label: "Express", value: "express" },
];

<Dropdown
  label="Delivery speed"
  options={speeds}
  value={speed}
  onValueChange={setSpeed}
/>
```

`Dropdown` and `Dropmenu` are the same component. This page calls it a dropdown, and both
names import: the component was renamed from `Select` to `Dropmenu` in 1.0.0, and `Dropdown`
is the alias that matches what the documentation says. One thing keeps the original name:
the configuration section, `components.dropmenu`, because a key names the module rather than
the export. A theme written for either name configures the same trigger.

The trigger draws the label of the option whose `value` matches, so a set value is stated as
a name rather than as a code. `onValueChange` reports the value itself; `onChange` reports a
synthetic change event shaped like the browser's own `<select>`, for a form library that
listens for one. Pass whichever your state wants, or both.

`placeholder` is what the trigger says while no option matches, `"Dropdown..."` unless you
state otherwise. `initialValue` is the label shown when no option matches `value`, and it is
drawn as written rather than looked up among the options, so a real selection belongs in
`value`.

## Search and the menu

`isSearch` puts a search field at the top of the menu, focused as the menu opens, and typing
filters the options by label. It is off unless you ask for it. An empty result is not a blank
panel: the menu states "No options found" in a status region, so the outcome is announced.
`searchPlaceholder` and `searchInputName` name the field, and `belowList` renders under the
options, an "Add new" action or a note about where the list comes from.

The menu is a component with its own tokens, and the `menu` prop overrides them one key at
a time: `itemVariant` and `itemColor` for options at rest, `activeItemVariant` and
`activeItemColor` for the selected one, `radius` and `size` for the options themselves. It
renders into a portal at the document body by default, so a dropdown inside a scrolling
table or a clipped panel is not cut off; `menu={{ portal: false }}` keeps it inside its
parent when a container needs to hold it. An option marked `disabled` stays in the list,
announces that it is unavailable and cannot be chosen.

```tsx demo="forms/dropmenu-search"
```

## Props

```props Dropmenu
```

The trigger is a button, so it reads the field family's web defaults, `size: "md"` and
`variant: "bordered"`, while `radius` is not registered: it follows the application's
`defaultRadius`, and `color` follows `defaultColor`. Stating either under
`components.dropmenu` pins it for every dropdown in the product.

The menu resolves its own tokens rather than borrowing the trigger's: `itemVariant` falls
back to `ghost` and `activeItemVariant` to `faded`, the two option colours fall back to
`primary` with the application's `defaultColor` in between, `radius` follows the
application's `defaultRadius` and then `md`, and `size` is `md`. `portal` and `lockScroll`
are both on. Write any of them under `components.dropmenu.menu` to change them once, or in
the `menu` prop to change them for one instance.

## Accessibility

- The trigger is a real `<button type="button">` with `aria-haspopup="listbox"` and
  `aria-expanded`, and the field's label names it. The description and the validation
  message are referenced with `aria-describedby`, and an `error` status sets
  `aria-invalid`.
- The list is a `role="listbox"`; each option is a `role="option"` with `aria-selected`, and
  a disabled option carries `aria-disabled` and cannot be chosen. The checkmark beside the
  selected option is decoration on top of that state.
- <kbd>↑</kbd> and <kbd>↓</kbd> on the trigger open the menu. Inside, the arrows 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 <kbd>Escape</kbd>
  closes the menu and returns focus to the trigger. Every one of those moves skips a
  disabled option.
- A search with no matches announces "No options found" through a `role="status"` region, so
  an empty result is stated rather than left as a blank panel.

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

## Related

```related multi-select, radio, form
```
