HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Loading the reference
ListboxView SourceEdit in SandboxView MarkdownCopy MarkdownOpen in ClaudeOpen in CursorA list of options, from which you choose one or several.StableSince 0.1.0FormsUsageimport'@fusion.dev/helix/listbox'import'@fusion.dev/helix/option'// Optionimport'@fusion.dev/helix-headless/listbox'import'@fusion.dev/helix-headless/option'// OptionPreview
API ReferenceRoothelix-listboxA list of options, from which you choose one or several.
PropTypeDescriptionautocompletestringDefault"off"What a browser's autofill may choose, as a platform token such as
country or cc-exp-month, as a native <select> takes it.defaultFilterstringDefault""The filter text the list starts with, when filter is not set.defaultValuestringDefault""The value the control starts with. A form reset returns it to this value,
and to the value attribute where this one is not written, as a native
control resets to the value it declares.disabledbooleanDefaultfalseWhether the control is disabled and cannot be used.emptyTextstringDefault"No matches"The text shown and announced when there are no rows and none are loading.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.filterstringThe text the list is filtered by, if any.filterablebooleanDefaultfalseWhether the list shows a field for filtering it.filterDelaynumberDefault0How long typing in the filter field rests before the list is filtered, in
milliseconds. 0 filters on every keystroke. The attribute also takes a
CSS time, such as 300ms.filterLabelstringDefault"Filter"Placeholder text for the filter field.filterMatch((text: string, filter: string) => boolean)Whether an option is kept by the filter: a function given the option's
words and the filter, trimmed, that returns true to keep it showing, as
React Aria's Autocomplete takes filter. For matching that ignores
accents, matches the start of each word, or matches out of order.hintstringDefault""Help text shown under the control. A validation message replaces it.itemsreadonlyDataOptionItem[]The options as data, for a list too long to draw whole: each a value,
which is also its words, or a record with a value, a label and
disabled. Set, the list draws only the options in sight, and the ones
you write as children are not read.labelstringDefault""The field's label, which is also its accessible name. Content in the
label slot replaces it.layout"grid"|"stack"How the options are laid out, which the arrow keys follow: stack, one
under another, or grid, in rows and columns, as React Aria's ListBox
lays out cards or photos. With grid, Up and Down move within a column,
and Left and Right along the list, mirrored right to left.loadErrorstring|nullDefault""What the list says when its options could not be loaded, such as after a
request to a server fails. Empty, null or no attribute is no error, so
removing the attribute clears it.loadingbooleanDefaultfalseWhether the rows are still loading.loadingTextstringDefault"Loading"The text shown and announced while the rows load.manualbooleanDefaultfalseStops the arrow keys from choosing each option they move to. Enter, Space
or a click chooses the highlighted option.multiplebooleanDefaultfalseWhether more than one option can be chosen.namestringDefault""The name the control's value is submitted under.noResultsTextstringThe text shown when a filter hides every option of a list that has some.reorderablebooleanDefaultfalseLets a reader move options, once @fusion.dev/helix/listbox/reorder (or
@fusion.dev/helix-headless/listbox/reorder) is imported: Alt with an
arrow moves the highlighted option, and a pointer drags one. The list
moves no option itself: you move your options, or your items, on
helix-reorder. Without that import it does nothing, so a list that never
moves options carries none of the code.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.resultLabelstringWhat a screen reader hears when a filter leaves one option, where
results-label should not say it. {count} is the count.resultsLabelstringDefault"{count, plural, one {# result} other {# results}}"What a screen reader hears when a filter narrows the list. {count} is
how many options are left, written in the locale, and each language
writes the forms it has: {count, plural, one {# wynik} few {# wyniki} many {# wyników} other {# wyniku}}.selectedIndexnumberWhich option is chosen, as an index, or -1 where none is.selectedLabelstringDefault"{name}, selected"What VoiceOver hears as the highlight reaches a chosen option from the
filter field, on Apple devices. {name} is the option's words.valuestringThe control's current value, which its form submits.valueMissingMessagestringDefault"Choose one to continue."The message shown when the field is required and empty.
ReadTypeDescriptionformHTMLFormElement|nullThe form the control belongs to, or null.labelsNodeListThe labels associated with the control.optionsHelixHeadlessOption[]Every option, in the order they appear.typestringThe kind of list, as the platform names it: select-one or
select-multiple.validationMessagestringThe message the browser would show for the control, or an empty string.validityValidityStateWhether the control meets its constraints, and why not.valuesstring[]The chosen values, as an array whether or not multiple is set.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.willValidatebooleanWhether the control is checked when its form is submitted.
SlotDescription(default)The options, and any groups of them.emptyWhat the list shows when it has no options to show, for content richer than empty-text.errorWhat the list shows while load-error is set, for content richer than its text.feedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.filter-iconThe icon in the filter field. Defaults to a magnifying glass.hintThe hint, for content richer than plain text.labelThe label, for content richer than plain text.loadingWhat the list shows while its options load, for content richer than loading-text.no-resultsWhat the list shows when a filter hides every option, for content richer than no-results-text.
EventTypeDescriptionchangeEventFired after the value changes.helix-before-changeHelixBeforeChangeEventFired when the value is about to change, and cancelable.helix-before-reorderHelixBeforeReorderEventFired when an option is dropped at a new place, in a reorderable list with @fusion.dev/helix/listbox/reorder imported, with every value in the new order. Cancelable: cancel it to keep the option where it is.helix-filterHelixFilterEventFired before the list is filtered, and cancelable.helix-load-moreHelixLoadMoreEventFired once the list is scrolled within a screen of its end, once for each number of options, and not while loading is set. Add the next page of options and set loading while you fetch it.helix-reorderHelixReorderEventFired after helix-before-reorder when nobody canceled it. Move your options, or your items, to the order in keys. Cancelable: cancel it to say the move did not happen.inputEventFired after the value changes.
MethodTypeDescriptioncheckValidity() => booleanReturns whether the control is valid, and fires invalid on it when it is
not. The control shows no message for it: reportValidity() does that.focus(options: FocusOptions) => voidMoves focus to the control, as focusing a native control does.highlightValue(value: string) => voidPuts the highlight on the option holding value, without choosing it, so
the arrow keys move from there. Nothing changes where no option a reader
can reach holds value.navigate(event: KeyboardEvent) => voidRuns the list's own key handling for a caller whose focus is elsewhere.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestFilter(next: string) => booleanRequests a new filter, and returns whether the request went through.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.reveal() => voidScrolls the chosen option to the middle of the list, or the highlighted one
where nothing is chosen.setCustomValidity(message: string) => voidMarks the control invalid with message, or clears that with an empty
string, as on a native control. The form does not submit while it is set.
PartDescriptionemptyThe text shown when the list has no options to show, or the filter hides every one. :state(no-results) is set for the second.errorThe text shown while load-error is set.feedbackThe message that says what is wrong with the value.filter-iconThe icon beside the filter field.filter-markThe default icon beside the filter field, shown when none is slotted.hintHelp under the list.itemsThe list of options.labelThe label above the list.liveA copy of the empty and loading text, how many options a filter left, and each move in a reorderable list, in a region that screen readers announce when it changes. Visually hidden in the styled tier.loadingThe text shown while the options load.searchThe region that holds the filter field.search-fieldThe filter field.
CSS PropertyDescription--listbox-background-colorThe panel's fill. Set it to transparent when the list is already inside a panel.--listbox-borderThe panel's border, as a shorthand. Set it to none when the list is already inside a panel.--listbox-column-min-inline-sizeHow narrow a column may be with layout="grid". As many columns as fit are drawn. Defaults to 8rem.--listbox-drag-preview-background-colorThe fill behind the copy of an option a pointer drags.--listbox-drag-preview-border-colorThe color of the edge around the copy of an option a pointer drags.--listbox-drag-preview-border-widthThe width of the edge around the copy of an option a pointer drags. None by default, where the shadow lifts it.--listbox-drag-preview-opacityThe opacity of the copy of an option a pointer drags.--listbox-drag-preview-radiusThe corner radius of the copy of an option a pointer drags.--listbox-drag-preview-shadowThe shadow that raises the copy of an option a pointer drags over the page.--listbox-dragging-opacityThe opacity of an option being dragged, in a reorderable list with @fusion.dev/helix/listbox/reorder imported.--listbox-drop-indicator-colorThe color of the line where a dragged option would land.--listbox-drop-indicator-sizeThe thickness of the line where a dragged option would land.--listbox-error-colorThe color of the line shown while load-error is set.--listbox-max-block-sizeMaximum height of the list before it scrolls.
Custom stateDescriptionemptyThe list has no options to show: none were given, or the filter hid every one.errorWhile load-error is set.invalidThe control has an error to show, from the browser's validation or from your feedback.loadingWhile loading is set.no-resultsA filter hid every option of a list that has some.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Roothelix-headless-listboxA list of options, from which you choose one or several.
PropTypeDescriptionautocompletestringDefault"off"What a browser's autofill may choose, as a platform token such as
country or cc-exp-month, as a native <select> takes it.defaultFilterstringDefault""The filter text the list starts with, when filter is not set.defaultValuestringDefault""The value the control starts with. A form reset returns it to this value,
and to the value attribute where this one is not written, as a native
control resets to the value it declares.disabledbooleanDefaultfalseWhether the control is disabled and cannot be used.emptyTextstringDefault"No matches"The text shown when the filter hides every option.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.filterstringThe text the list is filtered by, if any.filterablebooleanDefaultfalseWhether the list shows a field for filtering it.filterDelaynumberDefault0How long typing in the filter field rests before the list is filtered, in
milliseconds. 0 filters on every keystroke. The attribute also takes a
CSS time, such as 300ms.filterLabelstringDefault"Filter"Placeholder text for the filter field.filterMatch((text: string, filter: string) => boolean)Whether an option is kept by the filter: a function given the option's
words and the filter, trimmed, that returns true to keep it showing, as
React Aria's Autocomplete takes filter. For matching that ignores
accents, matches the start of each word, or matches out of order.hintstringDefault""Help text shown under the control. A validation message replaces it.itemsreadonlyDataOptionItem[]The options as data, for a list too long to draw whole: each a value,
which is also its words, or a record with a value, a label and
disabled. Set, the list draws only the options in sight, and the ones
you write as children are not read.labelstringDefault""The field's label, which is also its accessible name. Content in the
label slot replaces it.layout"grid"|"stack"How the options are laid out, which the arrow keys follow: stack, one
under another, or grid, in rows and columns, as React Aria's ListBox
lays out cards or photos. With grid, Up and Down move within a column,
and Left and Right along the list, mirrored right to left.loadErrorstring|nullDefault""What the list says when its options could not be loaded, such as after a
request to a server fails. Empty, null or no attribute is no error, so
removing the attribute clears it.loadingbooleanDefaultfalseWhether the rows are still loading.loadingTextstringDefault"Loading"The text shown and announced while the rows load.manualbooleanDefaultfalseStops the arrow keys from choosing each option they move to. Enter, Space
or a click chooses the highlighted option.multiplebooleanDefaultfalseWhether more than one option can be chosen.namestringDefault""The name the control's value is submitted under.noResultsTextstringThe text shown when a filter hides every option of a list that has some.reorderablebooleanDefaultfalseLets a reader move options, once @fusion.dev/helix/listbox/reorder (or
@fusion.dev/helix-headless/listbox/reorder) is imported: Alt with an
arrow moves the highlighted option, and a pointer drags one. The list
moves no option itself: you move your options, or your items, on
helix-reorder. Without that import it does nothing, so a list that never
moves options carries none of the code.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.resultLabelstringWhat a screen reader hears when a filter leaves one option, where
results-label should not say it. {count} is the count.resultsLabelstringDefault"{count, plural, one {# result} other {# results}}"What a screen reader hears when a filter narrows the list. {count} is
how many options are left, written in the locale, and each language
writes the forms it has: {count, plural, one {# wynik} few {# wyniki} many {# wyników} other {# wyniku}}.selectedIndexnumberWhich option is chosen, as an index, or -1 where none is.selectedLabelstringDefault"{name}, selected"What VoiceOver hears as the highlight reaches a chosen option from the
filter field, on Apple devices. {name} is the option's words.valuestringThe control's current value, which its form submits.valueMissingMessagestringDefault"Choose one to continue."The message reported when the field is required and no option is chosen.
Absent, or empty, is this sentence, or the words registered for the page's
locale.
ReadTypeDescriptionformHTMLFormElement|nullThe form the control belongs to, or null.labelsNodeListThe labels associated with the control.optionsHelixHeadlessOption[]Every option, in the order they appear.typestringThe kind of list, as the platform names it: select-one or
select-multiple.validationMessagestringThe message the browser would show for the control, or an empty string.validityValidityStateWhether the control meets its constraints, and why not.valuesstring[]The chosen values, as an array whether or not multiple is set.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.willValidatebooleanWhether the control is checked when its form is submitted.
SlotDescription(default)The options, and any groups of them.emptyWhat the list shows when it has no options to show, for content richer than empty-text.errorWhat the list shows while load-error is set, for content richer than its text.feedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.filter-iconThe icon in the filter field. Defaults to a magnifying glass.hintThe hint, for content richer than plain text.labelThe label, for content richer than plain text.loadingWhat the list shows while its options load, for content richer than loading-text.no-resultsWhat the list shows when a filter hides every option, for content richer than no-results-text.
EventTypeDescriptionchangeEventFired after the value changes.helix-before-changeHelixBeforeChangeEventFired when the value is about to change, and cancelable.helix-before-reorderHelixBeforeReorderEventFired when an option is dropped at a new place, in a reorderable list with @fusion.dev/helix/listbox/reorder imported, with every value in the new order. Cancelable: cancel it to keep the option where it is.helix-filterHelixFilterEventFired before the list is filtered, and cancelable.helix-load-moreHelixLoadMoreEventFired once the list is scrolled within a screen of its end, once for each number of options, and not while loading is set. Add the next page of options and set loading while you fetch it.helix-reorderHelixReorderEventFired after helix-before-reorder when nobody canceled it. Move your options, or your items, to the order in keys. Cancelable: cancel it to say the move did not happen.inputEventFired after the value changes.
MethodTypeDescriptioncheckValidity() => booleanReturns whether the control is valid, and fires invalid on it when it is
not. The control shows no message for it: reportValidity() does that.focus(options: FocusOptions) => voidMoves focus to the control, as focusing a native control does.highlightValue(value: string) => voidPuts the highlight on the option holding value, without choosing it, so
the arrow keys move from there. Nothing changes where no option a reader
can reach holds value.navigate(event: KeyboardEvent) => voidRuns the list's own key handling for a caller whose focus is elsewhere.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestFilter(next: string) => booleanRequests a new filter, and returns whether the request went through.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.reveal() => voidScrolls the chosen option to the middle of the list, or the highlighted one
where nothing is chosen.setCustomValidity(message: string) => voidMarks the control invalid with message, or clears that with an empty
string, as on a native control. The form does not submit while it is set.
PartDescriptionemptyThe text shown when the list has no options to show, or the filter hides every one. :state(no-results) is set for the second.errorThe text shown while load-error is set.feedbackThe message that says what is wrong with the value.filter-iconThe icon beside the filter field.filter-markThe default icon beside the filter field, shown when none is slotted.hintHelp under the list.itemsThe list of options.labelThe label above the list.liveA copy of the empty and loading text, how many options a filter left, and each move in a reorderable list, in a region that screen readers announce when it changes. Visually hidden in the styled tier.loadingThe text shown while the options load.searchThe region that holds the filter field.search-fieldThe filter field.
Custom stateDescriptionemptyThe list has no options to show: none were given, or the filter hid every one.errorWhile load-error is set.invalidThe control has an error to show, from the browser's validation or from your feedback.loadingWhile loading is set.no-resultsA filter hid every option of a list that has some.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Examples
NameDescriptionControlled FilterFilter text set by your code, for a list narrowed from a search box outside it.DisabledA disabled list, and a list disabled by the fieldset around it.EventsFiltering sends helix-filter, and choosing an option sends helix-before-change, input, and change.FilterableA search field above the list that narrows it as you type.GridOptions in rows and columns, which the arrow keys follow.InvalidA list with feedback that says no option is chosen.Loading And EmptyA list that is loading, and a list with no options that match the filter, each with its own text.Long ListTen thousand options given as data, of which only those in sight are drawn.MultipleSeveral options chosen at once.PreviewA list to choose one from, always open.PreviewA list to choose one from, always open.RequiredA required list, which must have an option chosen before the form submits.