Listboxes allow a user to select a value or multiple values from a custom-styled dropdown.
Listboxes should only be used when multiselect or custom styles are needed. If you can get by with using the browser styles provided by the component, you should use it first.
While Listbox is similar to the component, they differ in that listboxes represent a selection by the user. Items in a listbox do not have their own individual actions. You can use the ListboxButton component to easily present a listbox in a popout with a button that matches the appearance of our component.
import { Listbox, ListboxButton, useSelect, } from '@sproutsocial/racine'
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< Box display = " flex " alignItems = " center " >
< Text id = " mylabel " mr = { 300 } fontSize = { 300 } > Favorite Fruit </ Text >
< ListboxButton
minWidth = " 150px "
aria-labelledby = " mylabel "
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || "Select a fruit" }
</ ListboxButton >
</ Box >
)
}
Show more
Properties Name Type Default Description Required? children
React.Node
value
?string | string[]
Any item(s) matching this value will be rendered in a selected state onChange
(event) => ()
Called whenever a new value is selected. innerRef
React.Ref
Used if you need to compose Listbox with Downshift multiselect
boolean
false
Whether or not the listbox should allow multiple selections
Accessible labels There are two ways to make sure a Listbox has an accessible label.
Use aria-labelledby
with the same value as an id
on either text nearby that serves as a label or you can use VisuallyHidden text.
Note that the id
of the button component will be appended to the value of aria-labelledby
for accessibility.
This example will read “Favorite Fruit Select a Fruit”.
import { Listbox, ListboxButton, useSelect, } from '@sproutsocial/racine'
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< Box display = " flex " alignItems = " center " >
< Text id = " mylabel " mr = { 300 } fontSize = { 300 } > Favorite Fruit </ Text >
< ListboxButton
minWidth = " 150px "
aria-labelledby = " mylabel "
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || "Select a fruit" }
</ ListboxButton >
</ Box >
)
}
Show more
Use aria-label
with a text value that describes the function of the control.
Note that the value of the button will be appended to the value of aria-label
for accessibility.
This example will also read “Favorite Fruit Select a Fruit”.
import { Listbox, ListboxButton, useSelect, } from '@sproutsocial/racine'
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< ListboxButton
minWidth = " 150px "
aria-label = " Favorite Fruit "
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || "Select a fruit" }
</ ListboxButton >
)
}
Show more
Subcomponents Listbox group Groups are used to provide default padding and spacing around items, and can optionally render a visual label for a group of items.
< Listbox.Group title = " Fruit " >
< Box bg = " container.background.base " border = { 500 } borderColor = " container.border.base " p = { 400 } />
</ Listbox.Group >
Name Type Default Description Required? children
React.Node
title
React.Ref
If provided, a group header will be rendered in the listbox appearance
default
, flush
default
Use the flush appearance if you’re using the listbox group with a title outside of a popout disabled
boolean
false
If all of the items in a group are disabled, the group title should also be disabled
Listbox item Represents a unique value within a listbox. Selected items are indicated with a check icon and text.
< Box >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " selected >
Orange
</ Listbox.Item >
</ Box >
Name Type Default Description Required? children
React.Node
disabled
boolean
false
value
string
elemBefore
React.Node
A component to be rendered before the children of the menu item elemAfter
React.Node
A component to be rendered after the children of the menu item
Listbox checkbox A listbox item with a visible representing a selection.
< Listbox.Checkbox value = " Apple " > Apple </ Listbox.Checkbox >
Listbox radio A listbox item with a visible representing a selection.
< Listbox.Radio value = " Apple " > Apple </ Listbox.Radio >
Listbox filter input A special version of that can be used to allow the user to filter items within a listbox.
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< ListboxButton
minWidth = " 200px "
aria-label = " Favorite fruit "
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.FilterInput placeholder = " Filter items " mb = { 300 } />
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || "Select a fruit" }
</ ListboxButton >
)
}
Show more
Listbox divider A horizontal line with the “separator” role. Accepts the same props as
Recipes Changing the listbox button size ListboxButton offers a small
and large
size for matching the size of other elements in a form. The following example shows the small
size:
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< ListboxButton
minWidth = " 150px "
aria-label = " Favorite fruit "
size = ' small '
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || 'Select a fruit' }
</ ListboxButton >
)
}
Show more
Multiselect
( ) => {
const { value , onChange } = useMultiselect ( )
const currentOption =
value . length > 1 ? value . length + ' selected' : value . length ? value : null
return (
< ListboxButton
minWidth = " 150px "
aria-label = " Favorite fruit "
content = {
< Listbox multiselect onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group >
< Listbox.Checkbox value = " Apple " > Apple </ Listbox.Checkbox >
< Listbox.Checkbox value = " Orange " > Orange </ Listbox.Checkbox >
< Listbox.Checkbox value = " Banana " > Banana </ Listbox.Checkbox >
</ Listbox.Group >
</ Listbox >
}
>
{ currentOption || "Select a fruit" }
</ ListboxButton >
)
}
Show more
Groups
( ) => {
const { value , onChange } = useSelect ( { initialValue : null } )
return (
< ListboxButton
minWidth = " 150px "
aria-label = " Favorite fruit "
content = {
< Listbox onChange = { onChange } value = { value } width = " 200px " >
< Listbox.Group title = " Fruit " >
< Listbox.Item value = " Apple " > Apple </ Listbox.Item >
< Listbox.Item value = " Orange " > Orange </ Listbox.Item >
< Listbox.Item value = " Banana " > Banana </ Listbox.Item >
</ Listbox.Group >
< Listbox.Group title = " More fruit " >
< Listbox.Item value = " Kiwi " > Kiwi </ Listbox.Item >
< Listbox.Item value = " Papaya " > Papaya </ Listbox.Item >
< Listbox.Item value = " Mango " > Mango </ Listbox.Item >
</ Listbox.Group >
</ Listbox >
}
>
{ value || "Select a fruit" }
</ ListboxButton >
)
}
Show more