remix/ui/listbox
listbox is a headless option-list primitive for controlled selection and highlighting. Use it under components like select and combobox, or directly when you need custom listbox markup.
Primitive Usage
import type { Handle } from 'remix/ui'
import * as listbox from 'remix/ui/listbox'
import type { ListboxValue } from 'remix/ui/listbox'
import { listStyle, optionStyle } from './listbox.styles'
function FrameworkListbox(handle: Handle) {
let value: ListboxValue = 'remix'
let activeValue: ListboxValue = 'remix'
return () => (
<listbox.Context
value={value}
activeValue={activeValue}
onSelect={(nextValue) => {
value = nextValue
void handle.update()
}}
onHighlight={(nextValue) => {
activeValue = nextValue
void handle.update()
}}
>
<div aria-label="Frameworks" tabIndex={0} mix={[listStyle, listbox.list()]}>
{frameworks.map((option) => (
<div key={option.value} mix={[optionStyle, listbox.option(option)]}>
{option.label}
</div>
))}
</div>
</listbox.Context>
)
}
let frameworks = [
{ label: 'Remix', value: 'remix' },
{ disabled: true, label: 'React Router', value: 'react-router' },
{ label: 'React', value: 'react' },
{ label: 'Preact', value: 'preact' },
]Use textValue when the visible label is not the best string for typeahead search.
<div
mix={[
optionStyle,
listbox.option({
label: 'Staging',
textValue: 'beta',
value: 'staging',
}),
]}
>
Staging
</div>remix/ui/listbox
listbox.Context: provider for controlledvalueandactiveValue, option registration, selection, highlighting, optional ref access,flashSelection,selectionFlashAttribute, andonSelectSettled.listbox.list(): mixin that wiresrole="listbox", defaulttabIndex={-1}, keyboard navigation, focus scrolling, and typeahead highlighting.listbox.option(options): mixin that registers an option with requiredlabelandvalue, optionaldisabledandtextValue, and wiresrole="option", id, selected, disabled, highlighted, mouse, and click behavior.ListboxValue: selected or active value, represented asstring | null.ListboxContextandListboxProviderProps: provider context and prop types for controlled listboxes.ListboxOption: option input shape withlabel,value, optionaldisabled, and optionaltextValue.ListboxRegisteredOption: registered option metadata passed to callbacks and refs.ListboxRef: live ref object exposing active/selected options, option navigation, search matching, scrolling, and selection helpers.
Behavior Notes
- Selection and highlighting are controlled.
onSelectandonHighlightnotify the parent, but DOM state updates after the parent rerenders with new values. - Disabled options are skipped by keyboard navigation, typeahead, mouse movement, and click selection.
- Arrow keys wrap through enabled options.
HomeandEndmove to enabled boundaries.Enterand Space select the active option. - Typeahead highlights the next matching enabled option without selecting it and supports
textValue. flashSelectionappliesselectionFlashAttributefor 60ms, delaysonSelectSettled, and ignores new highlight/select interactions until the flash completes.