useListbox
Hook that manages listbox selection state, keyboard navigation, and option search.
- New York
- Rome
- London
- Istanbul
- Paris
Usage#
import { useListbox, useListboxOption } from '@primereact/headless/listbox';const listbox = useListbox({ options: cities, optionLabel: 'name' });
<div {...listbox.rootProps}>
<ul {...listbox.listProps}>
{listbox.getOptions().map((option, index) => {
const { optionProps, state } = useListboxOption({ option, index, context: listbox });
return <li {...optionProps}>{listbox.getOptionLabel(option)}</li>;
})}
</ul>
</div>;useListbox manages value state, keyboard focus cycling, type-ahead search, and ARIA attributes for option lists. See Primitive for a component-based API.
Features#
- Selection state — single or multiple selection with controlled or uncontrolled modes
- Keyboard navigation — arrow cycling, Home/End jumps, and built-in type-ahead that moves focus to matching options
- Option helpers —
getOptionLabel,getOptionValue,isSelected, andisOptionDisabledfor reading metadata off arbitrary option shapes - Grouping —
optionGroupLabel/optionGroupChildrenwith group header detection viauseListboxOption - Per-option hook —
useListboxOptionreturns ARIA-attributed props and state flags (selected,focused,disabled,group) for each row - Imperative hooks —
onOptionSelect(event, option, index)andonClearClick(event)for programmatic selection
Working with callbacks#
Controlled selection#
Pass value and onValueChange to drive the selection from outside state.
const [selected, setSelected] = React.useState(null);
const listbox = useListbox({
options: cities,
optionLabel: 'name',
value: selected,
onValueChange: (e) => setSelected(e.value)
});Multiple with meta-key additive selection#
Combine multiple with metaKeySelection to require Ctrl/Cmd for additive toggles, matching native multi-select semantics.
const listbox = useListbox({
options: cities,
optionLabel: 'name',
multiple: true,
metaKeySelection: true
});Grouped options#
Render group headers and options in a single pass using the per-option state from useListboxOption.
const listbox = useListbox({
options: groupedCities,
optionLabel: 'label',
optionGroupLabel: 'label',
optionGroupChildren: 'items'
});
listbox.getOptions().map((option, index) => {
const { optionProps, groupProps, state } = useListboxOption({ option, index, context: listbox });
if (state.group) return <div {...groupProps}>{listbox.getOptionGroupLabel(option)}</div>;
return <li {...optionProps}>{listbox.getOptionLabel(option)}</li>;
});Focus behavior tuning#
Use autoOptionFocus, selectOnFocus, and focusOnHover to shape how keyboard navigation and hover interact with selection.
const listbox = useListbox({
options: cities,
optionLabel: 'name',
autoOptionFocus: true,
selectOnFocus: true,
focusOnHover: true
});Styling with data attributes#
The hook exposes state through data-* attributes on each part. Use them as CSS selectors — no className juggling.
| Scope | Part | States |
|---|---|---|
listbox | option | data-selected, data-unselected, data-focused, data-disabled |
[data-scope='listbox'][data-part='option'][data-selected] {
background-color: #eff6ff;
color: #1d4ed8;
}
[data-scope='listbox'][data-part='option'][data-focused] {
outline: 1px solid #3b82f6;
}
[data-scope='listbox'][data-part='option'][data-disabled] {
opacity: 0.6;
pointer-events: none;
}API#
useListbox#
| Name | Type | Default |
|---|---|---|
value | unknown | — |
| The current value of the listbox. For single selection, this is a single value. For multiple selection, this is an array of values. | ||
defaultValue | unknown | — |
| The default value of the listbox when used in uncontrolled mode. | ||
options | T[] | — |
| An array of options to display in the listbox. | ||
optionKey | string | — |
| Unique key for each option. | ||
optionLabel | string | — |
| Label field for each option. | ||
optionValue | string | — |
| Value field for each option. | ||
optionDisabled | string | — |
| Field to check if an option is disabled. | ||
optionGroupLabel | string | — |
| Label field for option groups. | ||
optionGroupChildren | string | — |
| Field that contains the children options in a group. | ||
disabled | boolean | — |
| When present, it specifies that the listbox should be disabled. | ||
invalid | boolean | — |
| When present, it specifies that the component should have invalid state style. | ||
locale | string | — |
| The locale to use for localization. Used for accessibility labels. | ||
multiple | boolean | — |
| When present, allows selecting multiple options. | ||
metaKeySelection | boolean | — |
| When enabled, requires holding the meta key (Ctrl/Cmd) to select/deselect items in multiple selection mode. | ||
autoOptionFocus | boolean | — |
| When enabled, the focused option is automatically highlighted. | ||
selectOnFocus | boolean | — |
| When enabled, the focused option is automatically selected. | ||
focusOnHover | boolean | — |
| When enabled, the focused option changes on hover. | ||
tabIndex | number | — |
| Index of the element in tabbing order. | ||
onValueChange | (event: useListboxValueChangeEvent) => void | — |
| Callback to invoke when the value changes. | ||
useListboxOption#
| Name | Type | Default |
|---|---|---|
option | unknown | — |
| The option data object. | ||
index | number | — |
| The index of the option in the list. | ||
group | boolean | false |
| Whether the option is a group header. | ||
disabled | boolean | false |
| Whether the option is disabled. | ||
context | useListboxInstance | — |
| The parent listbox instance providing state and methods. | ||
Accessibility#
Arrow keys navigate options, Space selects with multi-select support, Home/End jump to ends, and Ctrl+A selects all in multiple mode. See Primitive for full WAI-ARIA compliance details.