Placeholder
<Select
placeholder="Choose an option"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
Selected option
<Select
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
With icon
Accepts icon or image URL/Data URLs.
<Select
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First', icon: <SvgFolder /> },
{ value: 'second', title: 'Second', icon: <SvgLock /> },
{ value: 'third', title: 'Third', icon: 'https://cdn.loom.com/assets/favicons-loom/favicon-32x32.png' },
]}
/>
See the Icon set.
Disabled
<Select
isDisabled
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
Disabled option
<Select
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third', isDisabled: true },
{ value: 'fourth', title: 'Fourth', icon: <SvgLock />, isDisabled: true },
{ value: 'fifth', title: 'Fifth', icon: 'https://cdn.loom.com/assets/favicons-loom/favicon-32x32.png', isDisabled: true },
]}
/>
Hidden and disabled option
This option is hidden and disabled. It can be used to show the selected option when it's not available in the list.
When an option is hidden, it will be visually removed from the list, but it will still be available in the DOM. And can still be selected through input controls (keyboard, mouse, touch, etc.) and screen readers.
Combined with the isDisabled
prop, the option will be inaccessible from input controls (keyboard, mouse, touch, etc.) and hidden visually as well as from screen readers.
<Select
selectedOptionValue="third"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Cannot select me again', hidden: true, isDisabled: true },
]}
/>
With divider
Use to visually separate items without needing labels.
Good for: Simple visual breaks, especially in action menus.
<Select
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third', hasDivider: true },
]}
/>
With group
Use when items fall into clear, labeled categories that help users navigate.
Good for: Large lists with meaningful, named categories.
<Select
selectedOptionValue="second"
options={[{
group: 'Group 1',
items: [
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },]
}, {
group: 'Group 2',
items: [
{ value: 'fourth', title: 'fourth', icon: <SvgAdd /> },
{ value: 'fifth', title: 'fifth', icon: <SvgArchive /> },
{ value: 'sixth', title: 'sixth', icon: <SvgZap /> },]
}
]}
/>
Menu max width and height
<div>
<Select
menuMaxHeight={24}
selectedOptionValue="Second"
options={demoText.ordinals.map((ordinal) => {
return { value: ordinal, title: ordinal }
})}
/>
<Spacer bottom="small" />
<Select
menuMaxWidth={24}
trigger={(triggerContent, buttonProps) => (
<TextButton icon={<SvgChevronDown />} iconPosition="right" {...buttonProps}>
{triggerContent.title}
</TextButton>
)}
selectedOptionValue="Second"
options={demoText.ordinals.map((ordinal) => {
return { value: ordinal, title: ordinal }
})}
/>
</div>
Menu can be positoned on the left or right side relative to the trigger. Wrap the <Select>
component so it doesn’t take up full width and set menuMinWidth
accordingly.
<Arrange gap="medium" justifyContent="space-between">
<Select
menuPosition="left"
menuMinWidth={14}
placeholder="Left"
options={[
{ value: 'a', title: 'A' },
{ value: 'b', title: 'B' },
{ value: 'c', title: 'C' },
]}
/>
<Select
menuPosition="right"
menuMinWidth={14}
placeholder="Right"
options={[
{ value: 'a', title: 'A' },
{ value: 'b', title: 'B' },
{ value: 'c', title: 'C' },
]}
/>
</Arrange>
Container
Specify where it's going to be rendered in the DOM, this is especially useful when working with Shadow DOM.
<Select
container={() => document.querySelector("#renderContainer")}
options={[{ value: 'bahamas', title: 'Bahamas' }]}
/>
onChange callback
<Select
selectedOptionValue="second"
onChange={option => {console.log(option)}}
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
onOuterClick callback
<Select
onChange={(option) => console.log(option)}
selectedOptionValue="second"
onOuterClick={() => console.log('onOuterClick')}
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
onOpenChange callback
Callback that provides the isOpen
value when dropdown opens or closes.
<Select
onChange={(option) => console.log(option)}
selectedOptionValue="second"
onOpenChange={newState => console.log(newState)}
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
Custom trigger
Use a custom button to trigger the menu. Make sure the trigger element is a button.
With TextButton
<Select
trigger={(triggerContent, buttonProps) => (
<TextButton icon={<SvgChevronDown />} iconPosition="right" {...buttonProps}>
{triggerContent.title}
</TextButton>
)}
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
menuMaxWidth={20}
onChange={option => {console.log(option)}}
/>
With placeholder
<Select
trigger={(triggerContent, buttonProps) => (
<button
disabled={triggerContent.isDisabled}
{...buttonProps}
>
<Text fontWeight={triggerContent.title && 'medium'}>
{triggerContent.title || triggerContent.placeholder}
</Text>
</button>
)}
placeholder="Choose an option"
options={[
{ value: 'apple', title: 'Apple' },
{ value: 'windows', title: 'Windows' },
]}
menuMaxWidth={20}
onChange={option => {console.log(option)}}
/>
With icons and selected option
<Select
trigger={(triggerContent, buttonProps) => (
<TextButton
{...buttonProps}
style={{
display: 'flex',
alignItems: 'center',
gap: 'var(--lns-space-xsmall)'
}}
icon={<SvgChevronDown />}
iconPosition="right"
>
<Icon icon={triggerContent.icon}/>
{triggerContent.title}
</TextButton>
)}
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First', icon: <SvgAdd /> },
{ value: 'second', title: 'Second', icon: <SvgLock /> },
{ value: 'third', title: 'Third', icon: <SvgZap /> },
]}
menuMaxWidth={20}
onChange={option => {console.log(option)}}
/>
Display custom trigger based on selected value
<Select
trigger={({title, value}, buttonProps) => (
<TextButton {...buttonProps}>
The value for '{title}' backwards is '{value.split('').reverse().join('')}'
</TextButton>
)}
selectedOptionValue="second"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
menuMaxWidth={20}
/>
With error
<Select
placeholder="Choose an option"
hasError={true}
errorMessage="Sample Error Message"
options={[
{ value: 'first', title: 'First' },
{ value: 'second', title: 'Second' },
{ value: 'third', title: 'Third' },
]}
/>
Props
menuMaxHeight
string | number
34
menuPosition
'left' | 'right' | 'topRight' | 'topLeft'
'left'
errorMessage
string
"Oops, that didn't work."
onChange
(selectedOption: OptionsObject) => void
placeholder
React.ReactNode
selectedOptionValue
string | null
menuMaxWidth
string | number
menuMinWidth
string | number
options
OptionsObject[] | GroupedOptionsObject[]
onOpenChange
(isOpen: boolean) => void
trigger
(triggerContent, buttonProps) => void