Select

18 parts

A custom, fully stylable replacement for the native <select> element: a trigger button that opens a floating listbox of options, with full keyboard support (arrow keys, Home/End, type-ahead search), focus trapping, and an optional hidden native <select> for native form submission. Use it when you need a single- or multi-choice dropdown whose menu and options must be styled beyond what a native control allows. The root owns the selected value and open state and provides context to every part; bind v-model for the value and v-model:open (or listen to update:modelValue / update:open) to control or observe it. Values may be strings, numbers, booleans, or objects (compared via by). Compose it from a SelectTrigger (with SelectValue/SelectIcon) plus a portalled SelectContent of SelectItems.

Demo

Loading demo…

Anatomy

Import the parts and compose them. Each part forwards attributes to its underlying element.

vue
import {
  SelectRoot,
  SelectTrigger,
  SelectValue,
  SelectIcon,
  SelectPortal,
  SelectContent,
  SelectViewport,
  SelectScrollUpButton,
  SelectScrollDownButton,
  SelectGroup,
  SelectLabel,
  SelectItem,
  SelectItemText,
  SelectItemIndicator,
  SelectSeparator,
  SelectArrow,
  SelectProvider,
  SelectBubbleSelect,
} from '@robonen/primitives/selection/select';

<SelectRoot>
  <SelectTrigger />
  <SelectValue />
  <SelectIcon />
  <SelectPortal />
  <SelectContent />
  <SelectViewport />
  <SelectScrollUpButton />
  <SelectScrollDownButton />
  <SelectGroup />
  <SelectLabel />
  <SelectItem />
  <SelectItemText />
  <SelectItemIndicator />
  <SelectSeparator />
  <SelectArrow />
  <SelectProvider />
  <SelectBubbleSelect />
</SelectRoot>

API Reference

SelectRoot

Root

A custom, fully stylable replacement for the native `<select>` element: a trigger button that opens a floating listbox of options, with full keyboard support (arrow keys, Home/End, type-ahead search), focus trapping, and an optional hidden native `<select>` for native form submission. Use it when you need a single- or multi-choice dropdown whose menu and options must be styled beyond what a native control allows. The root owns the selected value and open state and provides context to every part; bind `v-model` for the value and `v-model:open` (or listen to `update:modelValue` / `update:open`) to control or observe it. Values may be strings, numbers, booleans, or objects (compared via `by`). Compose it from a `SelectTrigger` (with `SelectValue`/`SelectIcon`) plus a portalled `SelectContent` of `SelectItem`s.

PropTypeDescription
modelValue?SelectModelValue<T, Multiple>Controlled value. Bind with v-model.
dir?DirectionReading direction. Falls back to ConfigProvider.
disabled?booleanDisable the whole select.
required?booleanMark field as required for native form validation.
name?stringNative input name for form submission.
defaultValue?SelectModelValue<T, Multiple>Uncontrolled default value.
defaultOpen?booleanUncontrolled default open state.
multiple?MultipleAllow selecting multiple options; the model becomes an array.
by?string | ((a: T, b: T) => boolean)Compare object values by a property key or a custom comparator. Omitted → === for primitives / structural deep-equality for objects.
autocomplete?stringNative autocomplete attribute forwarded to the hidden native select.
open?booleanTwo-way bound value (v-model:open).
Emits
EventPayload
update:open[value: boolean]

SelectTrigger

Trigger

The button that toggles the select open and anchors the floating content. Renders as a `role="combobox"` control wired with the appropriate ARIA and `data-state`/`data-placeholder` attributes; place a `SelectValue` and `SelectIcon` inside it. Supports type-to-select while closed and touch-device pointer hardening.

PropTypeDescription
disabled?booleanDisable this trigger independently from the root.

SelectValue

Value

Displays the label(s) of the currently selected option(s) inside the trigger, or the `placeholder` when nothing is selected. Renders into a non-interactive span so pointer events fall through to the trigger. Exposes the resolved `selectedLabel` array and raw `modelValue` to its default slot for custom rendering (e.g. multi-value chips), and reflects a `data-placeholder` attribute while empty.

PropTypeDescription
placeholder?stringText shown when no option is selected.

SelectIcon

Icon

The decorative icon shown in the trigger (a chevron by default). Marked `aria-hidden`; override the default glyph by passing slot content.

No props or events — renders its element and forwards attributes.

SelectPortal

Portal

Teleports the `SelectContent` into a different part of the DOM (the document body by default) so it escapes overflow and stacking-context clipping.

No props or events — renders its element and forwards attributes.

SelectContent

Content

The floating panel that holds the options. While open it mounts `SelectContentImpl` behind `Presence` (so it can animate in and out); while closed it still renders the options into a detached `DocumentFragment` so each `SelectItem` registers its value/label and `SelectValue` shows the initially-selected label before the dropdown is ever opened. Usually placed inside a `SelectPortal` and contains a `SelectViewport` of `SelectItem`s.

PropTypeDescription
forceMount?booleanForce mounting (keeps the panel in the DOM) for externally-controlled animation libraries.

SelectViewport

Viewport

The scrollable region inside the content that wraps the options. Marked `role="presentation"` (the listbox role lives on the content element), caps its height to the available space, and scrolls when the list overflows. In `item-aligned` mode it grows the panel as you scroll (MacOS-style). Pair it with the scroll buttons for an item-aligned menu.

PropTypeDescription
nonce?stringCSP nonce for the injected scrollbar-hiding <style> tag. Falls back to the active ConfigProvider nonce.

SelectScrollUpButton

ScrollUpButton

No props or events — renders its element and forwards attributes.

SelectScrollDownButton

ScrollDownButton

No props or events — renders its element and forwards attributes.

SelectGroup

Group

Groups a set of related items under a shared label. Renders as a `role="group"` and provides an id so a child `SelectLabel` can label the group for assistive technology.

No props or events — renders its element and forwards attributes.

SelectLabel

Label

A non-selectable heading for a `SelectGroup`. Renders the text that labels the group and wires its id to the group's `aria-labelledby`; must be used inside a `SelectGroup`.

No props or events — renders its element and forwards attributes.

SelectItem

Item

A single selectable option. Renders as a `role="option"`, registers its value and text with the root, becomes (or toggles, when `multiple`) the selected value on click/Enter/Space, and exposes `data-state`/`data-disabled`/ `data-highlighted` for styling. Holds a `SelectItemText` and, optionally, a `SelectItemIndicator`. The value may be any {@link AcceptableValue}.

PropTypeDescription
valueTThe option value. Must not be an empty string.
disabled?booleanDisable this item.
textValue?stringOptional text used for typeahead. Defaults to the SelectItemText content; set it when the item content is complex or non-textual.

SelectItemText

ItemText

The visible label of a `SelectItem`. Its text is what the root captures to show in `SelectValue` once the item is chosen, so each item should contain exactly one; use inside a `SelectItem`.

No props or events — renders its element and forwards attributes.

SelectItemIndicator

ItemIndicator

A marker (typically a checkmark) rendered only while its `SelectItem` is the selected option. Decorative and `aria-hidden`; use inside a `SelectItem`.

No props or events — renders its element and forwards attributes.

SelectSeparator

Separator

A visual divider between groups or items in the content. Renders as a horizontal `role="separator"` and is purely decorative.

No props or events — renders its element and forwards attributes.

SelectArrow

Arrow

No props or events — renders its element and forwards attributes.

SelectProvider

Provider

Re-provides the root context and a no-op content context so that `SelectItem`/`SelectItemText` can mount inside a detached `DocumentFragment` while the listbox is closed. This lets every option register its value and label up-front, so `SelectValue` shows the initially-selected label before the dropdown is ever opened. Internal — rendered by `SelectContent`.

PropTypeDescription
contextSelectRootContext

SelectBubbleSelect

BubbleSelect

A real, visually-hidden native `<select>` mirrored from the custom control so the value participates in native form submission, autofill, and `change` bubbling. Renders an `<option>` per registered item, supports `multiple`, and writes through the native value setter so frameworks that observe form controls (and the browser's autofill) see the change exactly as for a real `<select>`. Internal — rendered by `SelectRoot` when a `name` is set inside a form.

PropTypeDescription
autocomplete?string
disabled?boolean
multiple?boolean
name?string
required?boolean
optionsAcceptableValue[]Registered option values, rendered as native <option>s.
value?AcceptableValue | AcceptableValue[]Current model value(s).
Emits
EventPayload
change[value: string]