Select

Select dropdown with grouped options, per-item descriptions, multiple selection, action items, and column-based layouts.

import { Select } from "@plexui/ui/components/Select";

Examples

Overview

variant
size
checkPosition
clearable
multiple

With descriptions

variant
size
checkPosition
triggerIcon

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 searchAriaLabel for a more specific search label without changing the trigger's accessible name or the visible placeholder.

PropTypeDefaultDescription
optionsOptions<T>—Array of options or grouped options
valuestring | string[]—Selected value (single) or values (multiple)
onChange(option: T) => void | (options: T[]) => void—Called when selection changes, with the selected option (or options with multiple)
multiplebooleanfalseAllow multiple selection
placeholderstring"Select..."Trigger placeholder
variant"soft" | "outline" | "ghost""outline"Trigger variant
sizeControlSize"md"Trigger size (3xs to 3xl)
pillbooleanfalseRounded trigger
clearablebooleanfalseShow clear button
blockbooleanvariant !== "ghost"Full width trigger
disabledbooleanfalseDisable select. A disabled select is not submitted or validated with its form
loadingbooleanfalseLoading state; shows loadingPlaceholder and keeps the menu closed
loadingPlaceholderstring"Loading..."Trigger text while loading
namestring—Name of the hidden form input. With multiple, every selected value is submitted
requiredboolean—Required for native form validation
idstring—Id of the hidden form input
actionsarray—Actions below options list
checkPosition"start" | "end" | "none""start"Where the check indicator sits in the list. "none" removes the indicator column for lists that never carry a selection
OptionViewReact.FC—Custom option render
TriggerViewReact.FC—Custom trigger render: the selected option, or { values, selectedAll } with multiple
TriggerStartIconComponentType—Icon at the start of the trigger
trigger({ open, onToggle }) => ReactNode—Custom trigger element, wrapped as the popover trigger
dropdownIconType"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
listWidthnumber | "auto""auto"Width of the list in px
listMinWidthnumber | "auto"trigger width (300 when not block)Minimum width of the list in px
listMaxWidthnumber | "auto""auto"Maximum width of the list in px
searchPlaceholderstring—Search input placeholder
searchAriaLabelstring"Search options"Accessible name of the search input, independent of the trigger label
searchEmptyMessageReactNode"No results found."Shown when the search matches nothing
searchSizeControlSize"md"Size of the search input in the menu, such as 2xl for 44px touch targets on phones
searchPredicate(option, term) => boolean—Filters options while searching
aria-label / aria-labelledbystring—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 (default light-dark(var(--blue-500), var(--blue-300)))
  • --menu-font-size: font size (default var(--font-text-sm-size))
  • --menu-gutter: gutter (default spacing(1.5))
  • --menu-item-background-color: item background color (default light-dark(var(--alpha-08), var(--alpha-10)))
  • --menu-item-gap: item gap (default spacing(1.5))
  • --menu-item-padding: item padding (default spacing(1.5) spacing(2))
  • --menu-line-height: line height (default var(--font-text-sm-line-height))
  • --menu-radius: radius (default var(--radius-xl))
  • --menu-separator-background-color: separator background color (default var(--color-border))