Listbox is a component similar to a Dropdown, except that it allows arbitrary content within its choices. It might also display a label inside the component in addition to the chosen value. Listbox is only available in the React API for Visage, not in the vanilla JS version.
Basic Listbox
For a typical Listbox, we provide a BasicListbox
convenience component. It needs an aria-labelledby
prop whose value is the id of the element that labels it.
The BasicListbox
takes as children a set of ListboxOption
components:
Each
ListboxOption
must have avalue
prop holding that option's value.Each
ListboxOption
can also take an optionallabel
prop, which is what will shown in the Listbox proper when that option has been chosen. This is useful if you have additional content (such as a "New" callout) inside the option that you don't want to show up in the Listbox proper.
Inside each ListboxOption
you can put any HTML content you want, including bold text, colored text, Callouts, etc.
<BasicListbox><ListboxOption value="default">Choose a taco</ListboxOption><ListboxOption value="asada">Carne Asada</ListboxOption><ListboxOption value="pollo" label="Pollo" disabled>Pollo <Callout skin="holiday">Sold Out!</Callout></ListboxOption><ListboxOption value="pastor" label="Pastor">Pastor <Callout skin="announcement">New!</Callout></ListboxOption><ListboxOption value="lengua">Lengua</ListboxOption></BasicListbox>
full Listbox
If you can't use the BasicListbox convenience component, you can also use the API for the actual Listbox that underlies it:
<Listbox><ListboxButton /><ListboxPopover><ListboxList><ListboxOption value="default">Carne Asada</ListboxOption><ListboxOption value="pollo" label="Pollo" disabled>Pollo <Callout skin="holiday">Sold Out!</Callout></ListboxOption><ListboxOption value="pastor" label="Pastor">Pastor <Callout skin="announcement">New!</Callout></ListboxOption><ListboxOption value="lengua">Lengua</ListboxOption></ListboxList></ListboxPopover></Listbox>
Listbox with inner label
The Listbox can also support an inner label, where the Listbox will display the label on the left and the selected value on the right. You can't use the BasicListbox
convenience component for this.
The selected value shown on the right side depends on the following props of ListboxOption
:
labelNode: This accepts data of type ReactNode(handling complex JSX) and takes precedence over others if provided (Available v5.17 onwards).
label: This accepts data of type string only and is also used for accessibility.
If none of the above is provided, the ListboxOption
's children will be rendered as a plain string.
<Listbox><ListboxButtonWithLabel>Taco:</ListboxButtonWithLabel><ListboxPopover><ListboxList><ListboxOptionlabelNode={<Typography textColor="brand-blue">Carne</Typography>}label="Carne label"value="default">Carne Asada</ListboxOption><ListboxOption value="pollo" label="Pollo">Pollo <Callout skin="holiday">Sold Out!</Callout></ListboxOption><ListboxOption value="pastor">Pastor <Callout skin="announcement">New!</Callout></ListboxOption><ListboxOption value="lengua" disabled>Lengua</ListboxOption></ListboxList></ListboxPopover></Listbox>
Skins
"link" skin
The "link" skin makes the Listbox look much like a text link.
Here is an inline Listbox:
<p>Here is an inline Listbox:<BasicListbox skin="link"><ListboxOption value="default">Choose a taco</ListboxOption><ListboxOption value="asada">Carne Asada</ListboxOption><ListboxOption value="pollo" label="Pollo" disabled>Pollo <Callout skin="holiday">Sold Out!</Callout></ListboxOption><ListboxOption value="pastor" label="Pastor">Pastor <Callout skin="announcement">New!</Callout></ListboxOption><ListboxOption value="lengua">Lengua</ListboxOption></BasicListbox></p>
Other options
There are two other options for Listbox:
the
fullWidth
option makes the Listbox take up the full available width. (Compare to the Dropdown option of the same name.)the
sizeVariant="mini"
option, which makes the Listbox shorter than normal. (Compare to the Dropdown option of the same name.)
Guidelines
Accessibility Guidelines
Every Listbox needs an
aria-labelledby
prop whose value is the id of the element that labels it. (This is true even if the Listbox has an "inner label".) This labelling element can be made visually hidden if it shouldn't be shown to screens.
Components
Visage's Listbox is built on top of the reach-ui third-party component. See the Reach documentation for full prop descriptions.
Listbox
Prop | Type | Default | Description |
---|---|---|---|
onError | ReactEventHandler<HTMLDivElement> | ||
sizeVariant | "standard" | "mini" | "standard" | size (height) of the Listbox |
skin | "link" | "standard" | "error" | "standard" | skin of the Listbox |
fullWidth | boolean | false | Whether or not the Listbox should expand to fill the entire width of its container |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
BasicListbox
Prop | Type | Default | Description |
---|---|---|---|
arrow | ReactNode | Renders a text string or React node to represent an arrow inside the Listbox button. @see Docs https://reach.tech/listbox#listbox-arrow | |
button | ReactNode | ((props: { value: string; label: string; }) => ReactNode) | A render function or React node to to render the Listbox button's inner content. See the API for the ListboxButton children prop for details. @see Docs https://reach.tech/listbox#listbox-button | |
portal | boolean | Whether or not the popover should be rendered inside a portal. Defaults to
| |
onError | ReactEventHandler<HTMLDivElement> | ||
sizeVariant | "standard" | "mini" | "standard" | size (height) of the Listbox |
skin | "link" | "standard" | "error" | "standard" | skin of the Listbox |
fullWidth | boolean | false | Whether or not the Listbox should expand to fill the entire width of its container |
inModal | boolean | false | If you are using listbox inside ModalDialog |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ListboxPopover
Prop | Type | Default | Description |
---|---|---|---|
portal | boolean | Whether or not the popover should be rendered inside a portal. Defaults to
| |
position | Position | The positioning function for the popover. @see Docs https://reach.tech/listbox#listboxpopover-position | |
inModal | boolean | false | If you are using listbox inside ModalDialog |
All other props are forwarded to the element specified in thecomponent
prop(default: <span/>
)
ListboxOption
Prop | Type | Default | Description |
---|---|---|---|
labelNode | ReactNode | For showing label on the listbox button, not to be confused with label which is for accessibility |
All other props are forwarded to the element specified in thecomponent
prop(default: <li/>
)