Select
One choice from a list in a popup, with the label of the chosen item in the trigger, groups and disabled items.
A select shows the current choice in a compact trigger and opens a list to change it. Use it for a handful to a few dozen options that need no search; with more options, or when the reader knows what to type, use a combobox. When the options must be compared side by side, a radio group shows them all. On a phone, a native select opens the system picker.
Value: monthly
// apps/docs/examples/ui/select.tsx'use client';
import {useState} from 'react';
import { Field, FieldDescription, FieldLabel,} from '@workspace/active-ui/components/primitives/field';import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue,} from '@workspace/active-ui/components/primitives/select';
/** * One choice from a list in a popup. The trigger shows the label of the * chosen item, not its value: `Select` derives the labels from its items. * Items can be grouped under labels and disabled. */export default function SelectExample() { const [frequency, setFrequency] = useState<string | null>('monthly'); return ( <div className="grid w-full max-w-xs gap-6"> <Field> <FieldLabel id="select-frequency-label">Statement frequency</FieldLabel> <Select value={frequency} onValueChange={(value) => setFrequency(value)} > <SelectTrigger className="w-full" aria-labelledby="select-frequency-label" > <SelectValue /> </SelectTrigger> <SelectContent> <SelectItem value="monthly">Every month</SelectItem> <SelectItem value="quarterly">Every quarter</SelectItem> <SelectItem value="yearly">Every year</SelectItem> <SelectItem value="never" disabled> Never (required by law) </SelectItem> </SelectContent> </Select> <FieldDescription>Value: {frequency}</FieldDescription> </Field>
<Field> <FieldLabel id="select-zone-label">Time zone</FieldLabel> <Select> <SelectTrigger className="w-full" aria-labelledby="select-zone-label"> <SelectValue placeholder="Choose a time zone" /> </SelectTrigger> <SelectContent> <SelectGroup> <SelectLabel>Europe</SelectLabel> <SelectItem value="Europe/Amsterdam">Amsterdam</SelectItem> <SelectItem value="Europe/London">London</SelectItem> </SelectGroup> <SelectSeparator /> <SelectGroup> <SelectLabel>America</SelectLabel> <SelectItem value="America/New_York">New York</SelectItem> <SelectItem value="America/Chicago">Chicago</SelectItem> </SelectGroup> </SelectContent> </Select> </Field>
<Field> <FieldLabel id="select-size-label">Rows per page</FieldLabel> <Select defaultValue="25"> <SelectTrigger size="sm" aria-labelledby="select-size-label"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectItem value="10">10</SelectItem> <SelectItem value="25">25</SelectItem> <SelectItem value="50">50</SelectItem> </SelectContent> </Select> </Field> </div> );}Usage#
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from '@workspace/active-ui/components/primitives/select';
<Select value={frequency} onValueChange={setFrequency}> <SelectTrigger aria-labelledby="frequency-label"> <SelectValue placeholder="Choose" /> </SelectTrigger> <SelectContent> <SelectItem value="monthly">Every month</SelectItem> <SelectItem value="yearly">Every year</SelectItem> </SelectContent></Select>;The label in the trigger#
Base UI's select stores a value and shows it in Select; on its own that would show
monthly instead of "Every month". This package's Select reads the label of each Select
from its children and hands Base UI the pairs (items), so the trigger shows the label.
This works for string and number values written directly as
Selectchildren of the select, at any depth of plain JSX (groups included).Item Items rendered by a component of your own are invisible to that walk: pass
itemsyourself, as an array of{value, label}, or the trigger shows the raw value.For object values, give each object a
label, or passitem.To String Label
Anatomy#
Select: the value.valueandon(controlled), orValue Change default;Value multiplefor several values;namefor a native form.Select: the button that opens the list.Trigger size:defaultorsm.Select: the label of the chosen item, or theValue placeholder.Select: the popup. By default it opens over the trigger with the chosen item aligned to it (Content align); set it toItem With Trigger falseto open below.Select,Item SelectwithGroup Select,Label Select.Separator
What your application provides#
A label for the trigger:
aria-pointing at alabelledby Field, orLabel aria-.label The options and their labels; the value, when controlled.
A width: the trigger is as wide as its content (
w-); give itfit w-in a form.full
Accessibility and keyboard#
The trigger opens the list with
Enter,Spaceor the arrow keys; typing a letter jumps to the next item that starts with it.In the list, the arrow keys move,
Enterchooses and closes,Escapecloses without a change, and the focus returns to the trigger.A disabled item is skipped.
API#
Select#
Import from @workspace/
Generic over Value, Multiple extends boolean | undefined = false; the props below name them.
All props come from the Base UI part this component is built on.
Props
- Type
boolean
Whether the select popup is currently open.
- Type
boolean- Default
false
Whether the select popup is initially open.
To render a controlled select popup, use the open prop instead.
- Type
SelectInput Value<Value, Multiple> null
The uncontrolled value of the select when it's initially rendered.
To render a controlled select, use the value prop instead.
- Type
string
Provides a hint to the browser for autofill.
- Type
ReactNode
The content of this part, in the forms its type allows.
- Type
boolean- Default
false
Whether the component should ignore user interaction.
- Type
string
Identifies the form that owns the hidden input. Useful when the select is rendered outside the form.
- Type
boolean- Default
true
Whether moving the pointer over items should highlight them. Disabling this prop allows CSS :hover to be differentiated from the :focus (data-) state.
- Type
string
The id of the Select.
- Type
(itemValue, value) => boolean
Custom comparison logic used to determine if a select item value matches the current selected value. Useful when item values are objects without matching referentially. Defaults to Object. comparison.
- Type
readonly Group<any>[]readonly { label: ReactNode; valuโฆ Record<string, ReactNode>
Data structure of the items rendered in the select popup. When specified, <Select. renders the label of the selected item instead of the raw value.
- Type
(itemValue: Value) => string
When the item values are objects (<Select.), this function converts the object value to a string representation for display in the trigger. If the shape of the object is { value, label }, the label will be used automatically without needing to specify this prop.
- Type
(itemValue: Value) => string
When the item values are objects (<Select.), this function converts the object value to a string representation for form submission. If the shape of the object is { value, label }, the value will be used automatically without needing to specify this prop.
- Type
boolean- Default
true
Determines if the select enters a modal state when open.
true: user interaction is limited to the select: document page scroll is locked and pointer interactions on outside elements are disabled.false: user interaction with the rest of the document is allowed.
On touch devices, a true modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
- Type
Multiple- Default
false
Whether multiple items can be selected.
- Type
string
Identifies the field when a form is submitted.
- Type
boolean- Default
false
Whether the user should be unable to choose a different option from the select popup.
- Type
boolean- Default
false
Whether the user must choose a value before submitting a form.
- Type
RefObject<โฆ>
A ref to imperative actions.
unmount: Ends the closing phase of the select after an externally controlled closing animation finishes. CallpreventinUnmount On Close() onfirst, otherwise the select completes closing on its own. Whether it leaves the DOM is decided byOpen Change keepon the portal.Mounted close: Closes the select imperatively when called.
- Type
Ref<HTMLInputElement>
A ref to access the hidden input element.
Events
Called by the component when something happens.
- Type
(open, eventDetails) => void
Event handler called when the select popup is opened or closed.
- Type
(value, eventDetails) => void
Event handler called when the value of the select changes.
- Type
(open: boolean) => void
Event handler called after any animations complete when the select popup is opened or closed.
Takes only the props listed.
SelectContent#
Import from @workspace/
All props come from the Base UI part this component is built on.
Props
- Type
Align- Default
'center'
How to align the popup relative to the specified side.
- Type
boolean- Default
true
Whether the positioner overlaps the trigger so the selected item's text is aligned with the trigger's value text. This only applies to mouse input and is automatically disabled if there is not enough space.
- Type
number | OffsetFunction - Default
0
Additional offset along the alignment axis in pixels. Also accepts a function that returns the offset to read the dimensions of the anchor and positioner elements, along with its side and alignment.
The function takes a data object parameter with the following properties:
data.: the dimensions of the anchor element with propertiesanchor widthandheight.data.: the dimensions of the positioner element with propertiespositioner widthandheight.data.: which side of the anchor element the positioner is aligned against.side data.: how the positioner is aligned relative to the specified side.align
- Type
ReactNode
The content of this part, in the forms its type allows.
- Type
booleanRefObject<HTMLElement | null> (closeType) => โฆ
Determines the element to focus when the select popup is closed.
false: Do not move focus.true: Move focus based on the default behavior (trigger or previously focused element).Ref: Move focus to the ref element.Object function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior, orfalse/undefinedto do nothing.
- Type
Side- Default
'bottom'
Which side of the anchor element to align the popup against. May automatically change to avoid collisions.
- Type
number | OffsetFunction - Default
0
Distance between the anchor and the popup in pixels. Also accepts a function that returns the distance to read the dimensions of the anchor and positioner elements, along with its side and alignment.
The function takes a data object parameter with the following properties:
data.: the dimensions of the anchor element with propertiesanchor widthandheight.data.: the dimensions of the positioner element with propertiespositioner widthandheight.data.: which side of the anchor element the positioner is aligned against.side data.: how the positioner is aligned relative to the specified side.align
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Other parts#
SelectItem
All props come from the Base UI part this component is built on.
Props
- Type
ReactNode
The content of this part, in the forms its type allows.
- Type
boolean- Default
false
Whether the component should ignore user interaction.
- Type
string
Specifies the text label to use when the item is matched during keyboard text navigation.
Defaults to the item text content if not provided.
- Type
any- Default
null
A unique value that identifies this select item.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SelectScrollDownButton
All props come from the Base UI part this component is built on.
Props
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SelectScrollUpButton
All props come from the Base UI part this component is built on.
Props
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SelectSeparator
All props come from the Base UI part this component is built on.
Props
- Type
Orientation- Default
'horizontal'
The orientation of the separator.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SelectTrigger
Props marked Base UI are behaviour of the Base UI part this component is built on.
Props
- Type
ReactNode
The content of this part, in the forms its type allows.
- Type
boolean
Whether the component should ignore user interaction.
- Type
"default""sm"- Default
'default'
The height of the trigger: default (36 px) or sm (32 px).
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
SelectValue
All props come from the Base UI part this component is built on.
Props
- Type
(value) => ReactNode ReactNode
Accepts a function that returns a React to format the selected value. Treat the value as read-only: in multiple mode it may be a shared frozen array when nothing is selected.
- Type
ReactNode
The placeholder value to display when no value is selected. This is overridden by children if specified, or by a null item's label in items.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Parts that take only their elementโs attributes
Select: the attributes of its element, with className and ref, and Base UI'sGroup renderto use your own element.Select: the attributes of its element, with className and ref, and Base UI'sLabel renderto use your own element.
This page adapts the Select documentation of shadcn/ui (MIT licence) to this package; see Third-party notices.