Select component overview
multiple is enabled — from a predefined list. It pairs a styled trigger with a floating panel of bq-option elements and integrates with native HTML forms.
When to use
Use Select when
- The option list contains more than five items and a radio group would take too much space
- Users need to choose from a predefined set of values in a form
- Multiple selection from a long list is required and a checkbox group would be impractical
- The available choices are dynamic or loaded from an external source
Patterns
Single select
Single Select allows the user to pick one option from a menu.
Multiple select
Multiple Select supports independent choices. Add
enable-checkboxes when checkboxes make the multi-select state easier to scan. Selected items appear as dismissible tags in the input.Nested multiple select
Use nested options for selectable categories and their related choices. Parents cascade selection to their selectable descendants and show a mixed state when only some descendants are selected.
Anatomy
Select component anatomy
Design guidelines
Single vs. multiple selection
Nested multiple selection
Use nested options when people need to select a category, its related choices, or both. Nesting is available only withmultiple; single selects render only top-level options and log a browser warning when nested markup is present.
- Nested multi-select always renders checkboxes. You do not need
enable-checkboxes. - Selecting a parent selects its selectable descendants. Selecting a child also selects its selectable ancestors.
- A parent becomes indeterminate while only some of its selectable descendants are selected. Disabled and hidden descendants are not changed by a cascade.
- Use a unique
valuefor every option in the tree. Duplicate values are reported in the browser console because they make the value and event payload ambiguous.
Frontend (2); a fully selected branch keeps the parent label without a count.
Validation states
Usage
Default
Enhance user interaction by implementing the default select variant. Perfect for scenarios where you want users to choose from a list of options within a dropdown.Open
Use theopen attribute to display the select dropdown by default, offering users quick access to the available options without additional clicks. Use autofocus to keep the input focused on render.
Initial value
Set an initialvalue for the select component to preselect an option, providing a streamlined user experience and minimizing manual input.
Display value
ThedisplayValue property (display-value attribute) on bq-option overrides the value shown inside the input after selection. Use it when the full option content (e.g., multi-line layout) should not be collapsed into the input field.
Disabled
Employ thedisabled attribute to restrict user interaction with the select component temporarily, useful for scenarios where certain options are unavailable.
Multiple
Usemultiple to enable multiple selections. Add enable-checkboxes for a flat list when visible checkboxes make the current selections easier to scan. Use keep-open-on-select to keep the panel open while the user selects options. The max-tags-visible attribute controls how many tags are shown before a +N overflow tag appears.
Nested options
Nested options are a multiple-select pattern. Put child options in their parent’soptions slot and give every option a unique value. The parent below starts expanded with one selected child, so its checkbox is indeterminate and its tag shows the selected descendant count.
Set a fully selected branch
Usevalue to set and control the Select’s state. It stays a flat array, even when the options are nested.
1
Add the parent value
Include
"frontend" when the Frontend parent is selected.2
Add every selectable descendant
Include
"frontend:react" and "frontend:vue" to mark the whole Frontend branch as selected.Frontend and shows the all-selected-label summary in the open list.
HTML
Read a nested selection event
Listen forbqSelect when the selection changes. The event gives you two views of the same state:
selectionTree exists only for nested multi-select. It is undefined for flat and single Selects. Treat it as read-only output; keep using value to control the component.event.detail.selectionTree looks like this after selecting the full Frontend branch and Node.js:
Options
Prefix
Use theprefix slot to include additional visual elements or context, such as an icon, to provide users with extra visual cues about the field’s purpose.
Suffix
Leverage thesuffix slot to enhance the select component with extra elements. The default suffix is a rotating chevron caret; replace it with any icon to match your design context.
Validation
Usevalidation-status to signal the validation state (error, warning, or success) of the select component, ensuring accurate data input and real-time feedback.
Label with “Optional”
Choose this style when you want to include an optional label for additional context, providing users with guidance while maintaining a clean and unobtrusive design.Label with “Info Tooltip”
Enhance user understanding by incorporating abq-tooltip alongside the label, offering additional information or clarification about the select.
Panel placement
Adjust the panel placement to suit your layout. Use theplacement attribute to position the dropdown relative to the input — useful when the select is near the bottom of the viewport.
Visually hidden label
Keep an accessible label when the layout does not need one visibly. Use visually hidden text in thelabel slot, for example in a toolbar or compact table.
With no Helper Text
Select this variant when you don’t need additional helper text, giving users a straightforward and uncluttered experience.Non-searchable
Setdisable-search to keep the option panel usable while blocking any typing in the input. Users can still open the panel, browse options, and pick a value, but they cannot filter the list by typing. Use it when the option set is short enough to scan and you want to prevent free-text input from shrinking the visible options.
Keyboard focus alone keeps the panel closed. Press ArrowDown or ArrowUp to open it and move to an option.
The
readonly attribute currently has the same effect and is now deprecated — use disable-search instead. In a future major release, readonly will prevent changing the selected value rather than disabling filtering.Without clear button
Setdisable-clear to hide the clear button and prevent one-click deselection. Use this when selecting a value is required and removing it should not be trivially easy.
Custom behavior
CallpreventDefault() on the bqInput event to take full control of option filtering. This lets you implement async filtering, loading states, empty-state messages, and matched-text highlighting entirely in your own code.
Keyboard focus alone keeps the panel closed. With search enabled, typing opens it after the debounced bqInput event. Calling preventDefault() on that event stops automatic opening as well as built-in filtering. Set open yourself when your custom flow needs to show the panel.
Adding, replacing, or removing options preserves the text you are typing in both single- and multi-select. The search text is separate from value, which holds the committed selection. Selecting an option, clearing or resetting the field, or changing value programmatically replaces the search text with the selected label or an empty input.
In a searchable single-select, deleting all text or leaving only whitespace immediately clears the committed value and deselects the option. If a selection existed, this emits bqClear, even when your handler cancels bqInput. debounce-time delays the search event, not selection clearing. Editing a nonempty search draft keeps the previous selection; deleting a multi-select search draft keeps its selected tags.
For a controlled Select, handle bqClear to clear the selected value in your application or form state and reset the async query. Use the same handler for the clear button and text deletion. To show all options without removing a single selection, open the panel while keeping its selected label visible. Use reset(select.value) to cancel a search draft and restore that label.
For async results, keep selected options in the list when you need their labels or tags to remain visible. Ignore stale responses in your request handler so an older search does not replace newer results.
bqFocus and bqBlur track focus entering and leaving the whole Select. Moving between the input, options, and internal controls does not emit these events. Use bqBlur for field-level cleanup and call reset(select.value) to clear the search text without clearing the selection or remounting the control.
These events no longer follow input-only focus changes. If your handler needs to respond when the native input itself gains or loses focus, listen to that input’s native focus or blur event instead.
Form integration
bq-select is form-associated, so it participates in native submission, reset, and required validation. Use name for the submitted key, required for browser validation, and form-validation-message for a custom native validation message.
The live preview runs in an iframe sandbox that does not allow native form submission. Its Submit button uses
type="button" and bqClick to validate the form and display FormData without submitting it. The copyable examples use native type="submit" buttons for normal application forms.Best practices
DoAlways populate the
label slot so the select has an accessible name visible to all users, not just those relying on assistive technology.Don’tLeave the
label slot empty and rely solely on placeholder text — placeholder disappears once a value is selected and is not announced reliably by screen readers.DoWrite a clear, neutral placeholder such as “Choose a country” so users understand the field is interactive and what kind of value they are selecting.
Don’tUse the placeholder as a label substitute or write a directive like “Select” without context — this gives users no information about what the field is for.
DoUse
validation-status and the helper-text slot together when the field is required or has a validation error, so users understand exactly what is wrong and how to fix it.Don’tApply
validation-status="error" without a helper text message — a red border alone does not tell users what is wrong or how to correct it.DoProvide meaningful option labels that describe the value clearly — e.g., “Europe” instead of “EU”, “Pro plan ($49/mo)” instead of “pro”.
Don’tUse internal codes, abbreviations, or IDs as the visible option labels — what is meaningful in your database is not necessarily meaningful to users.
Accessibility
- Built in: the native
<input>inside the control hasrole="combobox",aria-haspopup("listbox"for flat options or"tree"for nested options),aria-expanded(toggled when the panel opens and closes), andaria-controlspointing to the options container byid. - Built in:
aria-disabled="true"is applied on the input whendisabledis set. - Built in: the component is form-associated via
ElementInternals, so it works with native<form>elements,requiredvalidation, andformResetCallback. - Built in: keyboard navigation —
Tabmoves focus to the input without opening the panel;ArrowDown/ArrowUpopen the panel and move focus to the first or last option; while the panel is open,ArrowDown/ArrowUpmove between options andHome/Endjump to the first or last option;EnterorSpaceselects the focused option;Escapecloses the panel and returns focus to the input without changing the selection. - Built in: in multi-select mode,
Backspaceon an empty input removes the most recently added tag. - Built in: opening the panel closes any other open select, date picker, or dropdown panel, so only one panel stays open at a time.
- Built in: nested multi-select changes the option container to a tree.
ArrowRightexpands a branch or moves to its first child;ArrowLeftcollapses a branch or returns to its parent.EnterandSpaceselect the focused option without changing expansion. - Built in: parent tree items expose checked, unchecked, or mixed state as their descendants are selected, and
aria-expandedcommunicates whether a branch is open. The separate visual expand button is hidden from assistive technology and removed from the Tab order; keyboard users expand and collapse the focused tree item with the arrow keys. - Your responsibility: provide text in the
labelslot. The component associates its native<label>with the combobox input throughforandid. Use visually hidden text when the layout cannot show a visible label. - Your responsibility: when
validation-statusis"error", populate thehelper-textslot with a clear error description. The component does not setaria-describedbyoraria-invalidon the input, so do not rely on color alone to communicate the error. - Your responsibility: if options are loaded asynchronously, show a disabled loading option in the default slot, as in the custom filtering example.
panelis a shadow part for styling, not a slot. - Your responsibility: give every nested option a unique
value. Values are used for selection state, form submission, tags, and theselectionTreeevent detail.
API reference
Properties
Methods
Events
Slots
Shadow parts
CSS custom properties
Resources
Interactive playground
Explore Select variants and states in Storybook
Source code
View the component source on GitHub