HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Loading the reference
SelectView SourceEdit in SandboxView MarkdownCopy MarkdownOpen in ClaudeOpen in CursorA control that opens a list of options to choose from.StableSince 0.1.0FormsUsageimport'@fusion.dev/helix/select'import'@fusion.dev/helix/option'// Optionimport'@fusion.dev/helix-headless/select'import'@fusion.dev/helix-headless/option'// OptionPreview
API ReferenceRoothelix-selectA control that opens a list of options to choose from.
PropTypeDescriptionautocompletestringDefault""What a browser's autofill may fill in, as a platform token such as
country or cc-exp-month, as on a native <select>.defaultOpenbooleanDefaultfalseWhether the element starts open. Ignored once open is written.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.emphasis"ghost"How strongly the trigger is drawn. Leave it unset for a framed field, or
set ghost for a trigger with no fill or edge.emptyTextstringDefault"No matches"The text shown when no options match the filter.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.filterablebooleanDefaultfalseWhether the list can be narrowed by typing.focusablebooleanDefaulttrueWhether the trigger holds its group's tab stop.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. Passed to the list, which draws only the options in sight,
as Listbox's items does. Set, the options 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.listLabelstringDefault"Options"The open list's name where nothing names the Select, read by screen
readers. The list has no visible name.loadingbooleanDefaultfalseWhether the options are still loading.loadingTextstringDefault"Loading"The text shown while the options load.multiplebooleanDefaultfalseWhether more than one option can be chosen.namestringDefault""The name the control's value is submitted under.openbooleanWhether the element is open.placeholderstringDefault"Choose"Shown on the trigger while nothing is chosen.position"floating"|"item-aligned"Default"floating"Where the list opens: floating, under the trigger and above it where
there is no room, or item-aligned, over the trigger with the chosen
option where the trigger is, as a native select does on macOS and Radix
Select does by default.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.selectedIndexnumberWhich option is chosen, as an index, or -1 where none is.valuestringThe control's current value, which its form submits.valueContent((chosen: readonlyHelixHeadlessOption[]) => unknown)What the trigger shows for the chosen options: a function given them, in
the order they appear, that returns text, an element or a Lit template.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.typestringThe kind of select, 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.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.endContent after the chosen value, such as a count, a unit, or a clear button.feedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.hintThe hint, for content richer than plain text.indicatorThe icon on the trigger that shows it opens, usually a caret.labelThe label, for content richer than plain text.startContent before the chosen value, such as an icon or a prefix.
EventTypeDescriptionchangeEventFired after the value changes.helix-before-changeHelixBeforeChangeEventRelayed from the listbox when the value is about to change. Cancelable: canceling it stops the change and leaves the decision to you.helix-before-closeHelixBeforeCloseEventFired before the list closes. Cancelable: canceling it keeps the list open and leaves the decision to you.helix-before-openHelixBeforeOpenEventFired before the list opens. Cancelable: canceling it keeps the list closed and leaves the decision to you.helix-filterHelixFilterEventFired as the user types in the filter field of a filterable select, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and filter the options yourself.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 and set loading while you fetch it.inputEventFired after the value changes.toggleToggleEventFired after the list opens or closes, with newState and oldState.
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.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestOpen(next: boolean) => booleanRequests that the element open or close, and returns whether the change
was applied.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.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.toggleOpen() => booleanRequests the opposite of the current state.
PartDescriptionfeedbackThe message that says what is wrong with the value.hintHelp under the trigger.indicatorThe caret that shows the control opens. Replaced by content in the indicator slot.labelThe label above the trigger.listboxThe list inside the panel.listbox-emptyThe text shown when the filter hides every option.listbox-errorThe inner list's error part, shown while its load-error is set.listbox-feedbackThe inner list's message that says what is wrong with the value.listbox-filter-iconThe icon beside the filter field.listbox-filter-markThe default icon beside the filter field, shown when none is slotted.listbox-hintHelp under the list.listbox-itemsThe list of options.listbox-labelThe label above the list.listbox-liveThe inner list's live part, the region screen readers announce its empty and loading text from.listbox-loadingThe text shown while the options load.listbox-searchThe region that holds the filter field.listbox-search-fieldThe filter field.liveThe region a screen reader announces a choice made on the closed trigger from, drawn once there is one to say. Visually hidden in the styled tier.surfaceThe floating panel.triggerThe closed control, which shows the chosen value.valueThe chosen option's text inside the trigger.
CSS PropertyDescription--floating-anchor-inline-sizeThe trigger's width, written on the panel while it is open, as in min-inline-size: var(--floating-anchor-inline-size). Read it; a value set here is written over.--floating-available-block-sizeThe room between the panel and the edge of the screen it opens toward, written on the panel while it is open. Read it; a value set here is written over.--select-border-colorColor of the panel's edge.--select-border-widthWidth of the panel's edge. Defaults to --helix-border-floating, which is 0, so the panel stands out by its shadow unless your theme sets a width.--select-shadowShadow under the panel. Defaults to --helix-shadow-floating, because the panel can sit over any content.--select-surface-max-block-sizeMaximum height of the panel.
Custom stateDescriptioninvalidThe control has an error to show, from the browser's validation or from your feedback.openWhile the list is open.placed-bottomWhile the open list sits below the trigger.placed-topWhile the open list sits above the trigger, where there was no room below.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Roothelix-headless-selectA control that opens a list of options to choose from.
PropTypeDescriptionautocompletestringDefault""What a browser's autofill may fill in, as a platform token such as
country or cc-exp-month, as on a native <select>.defaultOpenbooleanDefaultfalseWhether the element starts open. Ignored once open is written.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 no options match the filter.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.filterablebooleanDefaultfalseWhether the list can be narrowed by typing.focusablebooleanDefaulttrueWhether the trigger holds its group's tab stop.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. Passed to the list, which draws only the options in sight,
as Listbox's items does. Set, the options 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.listLabelstringDefault"Options"The open list's name where nothing names the Select, read by screen
readers. The list has no visible name.loadingbooleanDefaultfalseWhether the options are still loading.loadingTextstringDefault"Loading"The text shown while the options load.multiplebooleanDefaultfalseWhether more than one option can be chosen.namestringDefault""The name the control's value is submitted under.openbooleanWhether the element is open.placeholderstringDefault"Choose"Shown on the trigger while nothing is chosen.position"floating"|"item-aligned"Default"floating"Where the list opens: floating, under the trigger and above it where
there is no room, or item-aligned, over the trigger with the chosen
option where the trigger is, as a native select does on macOS and Radix
Select does by default.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.selectedIndexnumberWhich option is chosen, as an index, or -1 where none is.valuestringThe control's current value, which its form submits.valueContent((chosen: readonlyHelixHeadlessOption[]) => unknown)What the trigger shows for the chosen options: a function given them, in
the order they appear, that returns text, an element or a Lit template.valueMissingMessagestringDefault"Choose one to continue."The message reported when the field is required and nothing 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.typestringThe kind of select, 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.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.endContent after the chosen value, such as a count, a unit, or a clear button.feedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.hintThe hint, for content richer than plain text.indicatorThe icon on the trigger that shows it opens, usually a caret.labelThe label, for content richer than plain text.startContent before the chosen value, such as an icon or a prefix.
EventTypeDescriptionchangeEventFired after the value changes.helix-before-changeHelixBeforeChangeEventRelayed from the listbox when the value is about to change. Cancelable: canceling it stops the change and leaves the decision to you.helix-before-closeHelixBeforeCloseEventFired before the list closes. Cancelable: canceling it keeps the list open and leaves the decision to you.helix-before-openHelixBeforeOpenEventFired before the list opens. Cancelable: canceling it keeps the list closed and leaves the decision to you.helix-filterHelixFilterEventFired as the user types in the filter field of a filterable select, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and filter the options yourself.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 and set loading while you fetch it.inputEventFired after the value changes.toggleToggleEventFired after the list opens or closes, with newState and oldState.
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) => voidPuts focus on the trigger, which is what a toolbar moving its stop here asks.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestOpen(next: boolean) => booleanRequests that the element open or close, and returns whether the change
was applied.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.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.toggleOpen() => booleanRequests the opposite of the current state.
PartDescriptionfeedbackThe message that says what is wrong with the value.hintHelp under the trigger.indicatorThe caret that shows the control opens. Replaced by content in the indicator slot.labelThe label above the trigger.listboxThe list inside the panel.listbox-emptyThe text shown when the filter hides every option.listbox-errorThe inner list's error part, shown while its load-error is set.listbox-feedbackThe inner list's message that says what is wrong with the value.listbox-filter-iconThe icon beside the filter field.listbox-filter-markThe default icon beside the filter field, shown when none is slotted.listbox-hintHelp under the list.listbox-itemsThe list of options.listbox-labelThe label above the list.listbox-liveThe inner list's live part, the region screen readers announce its empty and loading text from.listbox-loadingThe text shown while the options load.listbox-searchThe region that holds the filter field.listbox-search-fieldThe filter field.liveThe region a screen reader announces a choice made on the closed trigger from, drawn once there is one to say. Visually hidden in the styled tier.surfaceThe floating panel.triggerThe closed control, which shows the chosen value.valueThe chosen option's text inside the trigger.
CSS PropertyDescription--floating-anchor-inline-sizeThe trigger's width, written on the panel while it is open, as in min-inline-size: var(--floating-anchor-inline-size). Read it; a value set here is written over.--floating-available-block-sizeThe room between the panel and the edge of the screen it opens toward, written on the panel while it is open. Read it; a value set here is written over.
Custom stateDescriptioninvalidThe control has an error to show, from the browser's validation or from your feedback.openWhile the list is open.placed-bottomWhile the open list sits below the trigger.placed-topWhile the open list sits above the trigger, where there was no room below.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Examples
NameDescriptionDisabledA disabled select, and a select disabled by the fieldset around it.EventsOpening the panel and changing the value, each with its own events.FilterableA search box in the list, for a set too long to scan.InlineAn inline select with no frame, as wide as its value, for a row of tools.InvalidA select with feedback that marks its value as invalid.Long ListTen thousand options given as data, of which the open list draws only those in sight.MultipleSeveral options chosen from one list.PreviewA native select with a label and a hint.PreviewA native select with a label and a hint.RequiredA required select, which must have a value before the form submits.