Select
Select dropdown with grouped options, per-item descriptions, multiple selection, action items, and column-based layouts.
import { Select } from "@plexui/vue/components/Select";Examples
Overview
With descriptions
Actions
Grouped options
Multiple selection
Column configuration
API
Use aria-labelledby with the ID of a visible field label. The default trigger includes that label and its current value or placeholder in its accessible name. aria-label, aria-describedby and aria-invalid also reach the default trigger. Custom triggers manage their own accessibility attributes.
The open list is a listbox (aria-multiselectable with multiple) named by aria-labelledby, then aria-label, then the default trigger; with a custom trigger, pass one of the two so the list has a name. aria-selected follows the selection and aria-activedescendant the highlighted option. Each option group is a group named by its label, so screen readers announce the group, and the arrow keys move through the options of every group in order. Typing a letter moves to the next matching option; Ctrl, Cmd and Alt shortcuts are left alone. After an option is chosen or Escape is pressed, focus returns to the trigger, a custom one included.
Searchable menus name their input Search options by default. Set search-aria-label for a more specific search label without changing the trigger's accessible name or the visible placeholder.
| Prop | Type | Default | Description |
|---|---|---|---|
options | Options<T> | — | Array of options or grouped options |
v-model:value | string | string[] | — | Selected value (single) or values (multiple) |
@change | (option | options) => void | — | Called when selection changes, with the selected option (or options with multiple) |
multiple | boolean | false | Allow multiple selection. value, @change and @update:value are typed by it |
placeholder | string | "Select..." | Trigger placeholder |
variant | "soft" | "outline" | "ghost" | "outline" | Trigger variant |
size | ControlSize | "md" | Trigger size (3xs to 3xl) |
pill | boolean | false | Rounded trigger |
clearable | boolean | false | Show clear button |
block | boolean | variant !== "ghost" | Full width trigger |
disabled | boolean | false | Disable select. A disabled select is not submitted or validated with its form |
loading | boolean | false | Loading state; shows loading-placeholder and keeps the menu closed |
loading-placeholder | string | "Loading..." | Trigger text while loading |
name | string | — | Name of the hidden form input. With multiple, every selected value is submitted |
required | boolean | — | Required for native form validation |
id | string | — | Id of the hidden form input |
actions | array | — | Actions below options list |
check-position | "start" | "end" | "none" | "start" | Where the check indicator sits in the list. "none" removes the indicator column for lists that never carry a selection |
#optionView / OptionView | slot (option) | Component | — | Custom option render |
#triggerView / TriggerView | slot | Component | — | Custom trigger render: the selected option, or { values, selectedAll } with multiple |
TriggerStartIcon | Component | — | Icon at the start of the trigger |
#trigger / trigger | slot ({ open, onToggle }) | function | — | Custom trigger element, wrapped as the popover trigger |
dropdown-icon-type | "chevronDown" | "dropdown" | "none" | "dropdown" | Indicator at the end of the trigger |
side | "top" | "bottom" | "bottom" | Preferred side of the list |
align | "start" | "center" | "end" | "center" when block, otherwise "start" | Alignment of the list against the trigger |
list-width | number | "auto" | "auto" | Width of the list in px |
list-min-width | number | "auto" | trigger width (300 when not block) | Minimum width of the list in px |
list-max-width | number | "auto" | "auto" | Maximum width of the list in px |
search-placeholder | string | — | Search input placeholder |
search-aria-label | string | "Search options" | Accessible name of the search input, independent of the trigger label |
#searchEmptyMessage / search-empty-message | slot | string | "No results found." | Shown when the search matches nothing |
search-size | ControlSize | "md" | Size of the search input in the menu, such as 2xl for 44px touch targets on phones |
search-predicate | (option, term) => boolean | — | Filters options while searching |
aria-label / aria-labelledby | string | — | Accessible name of the trigger and the list |
Select shares the unified 9-step size scale with Button, Input, SelectControl, and SegmentedControl.
Styling
Select reads these component tokens. Override them at any scope to restyle it:
--link-primary-text-color: primary text color (defaultlight-dark(var(--blue-500), var(--blue-300)))--menu-font-size: font size (defaultvar(--font-text-sm-size))--menu-gutter: gutter (defaultspacing(1.5))--menu-item-background-color: item background color (defaultlight-dark(var(--alpha-08), var(--alpha-10)))--menu-item-gap: item gap (defaultspacing(1.5))--menu-item-padding: item padding (defaultspacing(1.5) spacing(2))--menu-line-height: line height (defaultvar(--font-text-sm-line-height))--menu-radius: radius (defaultvar(--radius-xl))--menu-separator-background-color: separator background color (defaultvar(--color-border))