---
title: "Select Menu"
description: "A Discord-inspired string select: combobox trigger, keyboard-driven listbox and a portalled panel."
---

A complete combobox: a trigger, a search field, a keyboard-driven listbox and a panel that flips when it runs out of room below. This is the option picker from the client, not a styled `<select>`.

_Live example of Select Menu — see the page for the rendered demo._

## Installation

```bash
npx newtui@latest add select-menu
```

Files written — React: components/ui/select-menu.tsx. Vue: components/ui/select-menu/SelectMenu.vue, components/ui/select-menu/index.ts.

## Usage

React:

```tsx
import { SelectMenu } from "@/components/ui/select-menu"
```

Vue:

```ts
import { SelectMenu } from "@/components/ui/select-menu"
```

## API reference

**`SelectMenu`**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` | `SelectOption[]` | — | The choices: `{ value, label, description?, icon?, disabled? }`. |
| `value` | `string` | — | The selected value, when you control it. |
| `defaultValue` | `string` | — | The value selected on first render. |
| `onValueChange` | `(value: string) => void` | — | Called with the chosen value. |
| `placeholder` | `string` | — | Shown on the trigger while nothing is selected. |
| `searchable` | `boolean` | `false` | Adds the filter field above the list. |
| `disabled` | `boolean` | `false` | Makes the trigger inert. |

Every part also accepts the native attributes of the element it renders, and a `className` that is merged rather than replaced.

## Accessibility

The trigger is a `combobox` with `aria-expanded` and `aria-controls`; the panel is a `listbox` whose options carry `aria-selected`. `Up` and `Down` move the active option, `Home` and `End` jump to the ends, `Enter` selects, `Escape` closes and returns focus to the trigger. The active option is tracked with `aria-activedescendant`, so focus never leaves the trigger.

## Tokens

Select Menu reads its colours, radii and motion from the `--newt-*` tokens. Override a token rather than editing the component.
