Select
The Select components let you create lists of options for users to choose from.
Introduction
A select is a UI element that gives users a list of options to choose from.
Base UI offers components to replace the native HTML <select>
tag: Select.
It also includes Option for creating the options on the list, and Option Group for grouping those options.
Features
- 🦍 Can be used as a controlled or uncontrolled component
- 🧬 Accepts custom elements and non-string values for options
- 🗃️ Options can be grouped and nested
Components
Usage
After installation, you can start building with this component collection using the following basic elements:
import Select from '@mui/base/Select';
import Option from '@mui/base/Option';
export default function MyApp() {
return (
<Select>
<Option>{/* option one */}</Option>
<Option>{/* option two */}</Option>
</Select>
);
}
Basics
The following demo shows how to create and style a Select component.
Form submission
The value(s) chosen in the Select can be posted to a server using a standard HTML form.
When the name
prop is set, the Select will render a hidden input with the selected value.
Note how the second Select in the demo above renders a hidden input with the name provided as a prop.
You can customize the value of this hidden input. See the Object values section to learn how to do it.
TypeScript caveat
Select accepts generic props.
Due to TypeScript limitations, this may cause unexpected behavior when wrapping the component in forwardRef
(or other higher-order components).
In such cases, the generic argument will be defaulted to unknown
and type suggestions will be incomplete.
To avoid this, you can manually cast the resulting component to the correct type:
const CustomSelect = React.forwardRef(function CustomSelect<TValue>(
props: SelectProps<TValue>,
ref: React.ForwardedRef<HTMLUListElement>,
) {
// ...your code here...
return <Select {...props} ref={ref} />;
}) as <TValue>(
props: SelectProps<TValue> & React.RefAttributes<HTMLUListElement>,
) => JSX.Element;
For the sake of brevity, the rest of the demos throughout this doc will not use forwardRef
.
Multi-select
The Select component lets your users select multiple options from the list.
Set the multiple
prop to turn on the multi-selection mode.
Anatomy
The Select component is composed of a root <button>
along with a <div>
that houses a <ul>
within a Popper.
Option renders as an <li>
:
<button class="MuiSelect-root" type="button">Open</button>
<div class="MuiSelect-popper">
<ul class="MuiSelect-listbox">
<li class="MuiOption-root">Option one</li>
<li class="MuiOption-root">Option two</li>
</ul>
</div>
Custom structure
Use the slots
prop to override the root or any other interior slot:
<Select slots={{ root: 'div', listbox: 'ol' }} />
Use the slotProps
prop to pass custom props to internal slots.
The following code snippet applies a CSS class called my-listbox
to the listbox slot:
<Select slotProps={{ listbox: { className: 'my-listbox' } }} />
Portals
By default, the Select's popup is rendered in a Portal and appended to the bottom of the DOM.
To instead render the popup where the component is defined, override the disablePortal
prop of the underlying Popper, as shown below:
<Select slotProps={{ popper: { disablePortal: true } }} />
Usage with TypeScript
In TypeScript, you can specify the custom component type used in the slots.root
as a generic parameter of the unstyled component. This way, you can safely provide the custom root's props directly on the component:
<Select<typeof CustomComponent> slots={{ root: CustomComponent }} customProp />
The same applies for props specific to custom primitive elements:
<Select<'button'> slots={{ root: 'button' }} onClick={() => {}} />
Hooks
import useSelect from '@mui/base/useSelect';
The useSelect
hook lets you apply the functionality of a select to a fully custom component.
It returns props to be placed on the custom component, along with fields representing the component's internal state.
Hooks do not support slot props, but they do support customization props.
The following example shows a select built with a hook. Note how this component does not include any built-in classes. The resulting HTML is much smaller compared to the unstyled component version, as the class names are not applied.
Selected value: 10
Selected character:
{ "name": "Frodo", "race": "Hobbit" }
If you use a Select with object values in a form and post the form contents to a server, the selected value will be converted to JSON.
You can change this behavior with the help of the getSerializedValue
prop.
Selected value appearance
You can customize the appearance of the selected value display by providing a function to the renderValue
prop.
The element returned by this function will be rendered inside the select's button.
Option appearance
Options don't have to be plain strings. You can include custom elements to be rendered inside the listbox.
Grouping options
Options can be grouped, similarly to how the native <select>
element works.
Unlike the native <select>
, groups can be nested.
The following demo shows how to group options with the Option Group component: