Select
Displays a list of options for the user to pick from, triggered by a button.
Anatomy
Import and assemble the component:
1import { Select } from "@raystack/apsara";23<Select>4 <Select.Label />5 <Select.Trigger>6 <Select.Value />7 </Select.Trigger>8 <Select.Content>9 <Select.Status />10 <Select.Empty />11 <Select.Group>12 <Select.GroupLabel />13 <Select.Item />14 </Select.Group>15 <Select.Separator />16 </Select.Content>17</Select>
Usage
Appearance first, meaning size and variant, then how many items can be chosen, and who owns the value.
Basic Select
A trigger and a list of items. Select.Value renders the current selection in the trigger. A check mark shows the selected item in the list. In multiple mode, each item has a checkbox instead.
Pass items to the root so Select.Value can show the label of the selected value. It takes { value, label }[] or a value-to-label record. The list mounts only when it opens, so without items the trigger shows the raw value.
1<Select items={{ apple: "Apple", banana: "Banana" }}>2 <Select.Trigger aria-label="Fruit selection">3 <Select.Value placeholder="Select a fruit" />4 </Select.Trigger>5 <Select.Content>6 <Select.Item value="apple">Apple</Select.Item>7 <Select.Item value="banana">Banana</Select.Item>8 </Select.Content>9</Select>
Icon
Pass leadingIcon to Select.Item to show an icon before the item text.
1<Select2 items={{ apple: "Apple", banana: "Banana", grape: "Grape", orange: "Orange" }}3>4 <Select.Trigger aria-label="Fruit selection">5 <Select.Value placeholder="Select a fruit" />6 </Select.Trigger>7 <Select.Content>8 <Select.Item value="apple" leadingIcon={<Info size={16} />}>9 Apple10 </Select.Item>11 <Select.Item value="banana" leadingIcon={<X size={16} />}>12 Banana13 </Select.Item>14 <Select.Item value="grape" leadingIcon={<Home size={16} />}>
To show the icon in the trigger too, pass a function as the child of Select.Value. It receives the selected value.
1(function IconValue() {2 const fruits = {3 apple: { label: "Apple", icon: <Info size={16} /> },4 banana: { label: "Banana", icon: <Home size={16} /> },5 };67 return (8 <Select defaultValue="apple">9 <Select.Trigger>10 <Select.Value placeholder="Select a fruit">11 {(value) => (12 <Flex align="center" gap={2}>13 {fruits[value].icon}14 {fruits[value].label}
Label
Select.Label renders a visible label linked to the trigger. Clicking it focuses the trigger.
1<Flex direction="column" gap={2}>2 <Select items={{ apple: "Apple", banana: "Banana" }}>3 <Select.Label>Fruit</Select.Label>4 <Select.Trigger>5 <Select.Value placeholder="Select a fruit" />6 </Select.Trigger>7 <Select.Content>8 <Select.Item value="apple">Apple</Select.Item>9 <Select.Item value="banana">Banana</Select.Item>10 </Select.Content>11 </Select>12</Flex>
Size
Two sizes. medium is the default; small fits toolbars and table filters.
1<Flex align="center" gap={9}>2 <Select items={{ "1": "Option 1", "2": "Option 2" }}>3 <Select.Trigger size="small">4 <Select.Value placeholder="Small select" />5 </Select.Trigger>6 <Select.Content>7 <Select.Item value="1">Option 1</Select.Item>8 <Select.Item value="2">Option 2</Select.Item>9 </Select.Content>10 </Select>11 <Select items={{ "1": "Option 1", "2": "Option 2" }}>12 <Select.Trigger>13 <Select.Value placeholder="Medium select" />14 </Select.Trigger>
Variant
outline (the default) draws a bordered control. text removes the border for use inside a toolbar or beside other text.
1<Select items={{ all: "All", active: "Active", inactive: "Inactive" }}>2 <Select.Trigger>3 <Select.Value placeholder="Select..." />4 </Select.Trigger>5 <Select.Content>6 <Select.Item value="all">All</Select.Item>7 <Select.Item value="active">Active</Select.Item>8 <Select.Item value="inactive">Inactive</Select.Item>9 </Select.Content>10</Select>
With Separator
Select.Separator draws a rule between groups of items.
1<Select2 items={{ "1": "Option 1", "2": "Option 2", "3": "Option 3", "4": "Option 4" }}3>4 <Select.Trigger>5 <Select.Value placeholder="Select..." />6 </Select.Trigger>7 <Select.Content>8 <Select.Group>9 <Select.Item value="1">Option 1</Select.Item>10 <Select.Item value="2">Option 2</Select.Item>11 </Select.Group>12 <Select.Separator />13 <Select.Group>14 <Select.Item value="3">Option 3</Select.Item>
Multiple selection
To enable multiple selection, pass the multiple prop to the Select root element.
When multiple selection is enabled, the value, onValueChange, and defaultValue will be an array of strings.
1<Select2 multiple3 items={Array.from({ length: 10 }, (_, i) => ({4 value: String(i + 1),5 label: "Option " + (i + 1),6 }))}7>8 <Select.Trigger>9 <Select.Value placeholder="Select..." />10 </Select.Trigger>11 <Select.Content>12 <Select.Item value="1">Option 1</Select.Item>13 <Select.Item value="2">Option 2</Select.Item>14 <Select.Item value="3">Option 3</Select.Item>
Autocomplete
To enable autocomplete, pass the autocomplete prop to the Select root element.
With items, Base UI filters by label. Without items, the select filters items with a simple text match. For full control, set autocompleteMode="manual" and filter the items yourself.
Select.Empty shows its content only when no item matches the search. It needs items on the root. Select.Status is a polite live region for messages such as a result count or a loading state. Both work only in autocomplete mode.
1<Select2 autocomplete3 items={{4 apple: "Apple",5 banana: "Banana",6 blueberry: "Blueberry",7 grapes: "Grapes",8 pineapple: "Pineapple",9 }}10>11 <Select.Trigger>12 <Select.Value placeholder="Select a fruit" />13 </Select.Trigger>14 <Select.Content>
Controlled
Pass value with onValueChange to own the selection. Do this when the value comes from a form, a URL, or another control on the page.
1(function ControlledSelect() {2 const [fruit, setFruit] = React.useState("apple");34 return (5 <Flex direction="column" gap={5}>6 <Select7 value={fruit}8 onValueChange={setFruit}9 items={{ apple: "Apple", banana: "Banana", grapes: "Grapes" }}10 >11 <Select.Trigger width={200}>12 <Select.Value />13 </Select.Trigger>14 <Select.Content>
API Reference
The trigger, and the parts of the list it opens.
Root
The Select component is composed of several parts, each with their own props.
The root element is the parent component that holds the select. Using the autocomplete prop, you can enable autocomplete functionality.
Prop
Type
Trigger
The button that triggers the Select.
Prop
Type
Content
The container that holds the Select items.
Prop
Type
Set alignItemWithTrigger to open the list over the trigger, with the selected item lined up on the trigger's value. Base UI turns it off for touch input and when there is not enough space. side and align have no effect while it is on.
Item
Individual clickable options within the Select.
Prop
Type
Group
A way to group related Select items together.
Prop
Type
Value
Shows the label of the selected value, or the placeholder.
Prop
Type
Label
A visible label linked to the trigger.
Prop
Type
GroupLabel
The label of a Select.Group. Use it only inside Select.Group.
Prop
Type
Empty
Shows its content when no item matches the search. Autocomplete mode only.
Prop
Type
Status
A polite live region for status messages. Autocomplete mode only.
Prop
Type
Separator
Visual divider between Select items or groups.
Prop
Type
Slots
Every rendered part carries a stable data-slot attribute for styling and testing:
| Slot | Element |
|---|---|
select-trigger | The trigger button that opens the menu |
select-trigger-content | Flex wrapper around the trigger's children |
select-trigger-icon | The chevron dropdown icon in the trigger |
select-label | The label linked to the trigger |
select-value | The <span> showing the selected label or placeholder |
select-value-content | Wrapper around the chips in multiple mode |
select-value-overflow | The "+N" overflow count for multiple values (when they don't all fit) |
select-positioner | The floating positioner for the popup |
select-content | The popup container |
select-search | The search input (when autocomplete is enabled) |
select-list | The scrollable list of items |
select-group | A group of items |
select-group-label | The label of a group |
select-empty | The message shown when no item matches (autocomplete only) |
select-status | The live region for status messages (autocomplete only) |
select-separator | A divider between items or groups |
select-item | An individual option row |
select-item-icon | Leading icon on an item (when set) |
select-item-text | The text label of an item |
select-item-indicator | The check mark on the selected item (single selection only) |
Accessibility
The Select component follows WAI-ARIA guidelines:
- Trigger has role
combobox - Content has role
listbox - Items have role
option - ARIA labels and descriptions