bq-option-list is the required wrapper for bq-option and bq-option-group elements. It sets the role="listbox" context, handles keyboard and click events from child options, and emits a single bqSelect event with the selected item’s value back to the parent component.
bq-option-list is a structural container — it does not render any visible UI of its own. It is used internally by higher-level components such as bq-select and bq-dropdown. Use it directly only when you are building a custom listbox-based control.When to use
Use option list when
- You are composing a custom dropdown, command palette, or navigation menu from
bq-optionitems - You need a
role="listbox"container that bubbles selection events from child options to your component logic - You want to combine flat options with
bq-option-groupsections in the same list
Do not use option list when
- You are using
bq-selectorbq-dropdown— these components managebq-option-listinternally - You need a multi-select list with checkboxes — use form controls such as
bq-checkboxdirectly - The items are primarily navigational links rather than discrete selectable choices
Option List patterns
Flat list
A plain sequence of
bq-option items. Use when all choices belong to the same category and no visual separation is needed.Grouped list
One or more
bq-option-group containers inside the list. Use when choices fall into distinct named categories that help users scan faster.Mixed list
Ungrouped options above or below grouped sections. Use when a “pinned” set of common choices (for example, “Recently used”) should appear before the full categorized list.
Anatomy
bq-option-list is a single flex column container that holds slotted option items or option groups. It has no visual chrome of its own — the border, shadow, and background typically come from the enclosing panel or dropdown trigger.
| Part | Element | Description |
|---|---|---|
| 1 | Base | The internal <div> that stacks slotted options vertically with consistent gap |
| 2 | Option items | bq-option or bq-option-group elements placed in the default slot |
Design guidelines
Use with a containing surface
bq-option-list provides layout and interaction semantics but no background or border. Wrap it in a surface element — typically a panel, popover, or card — that provides the visual boundary users associate with a dropdown or list.
When used inside
bq-select or bq-dropdown, the containing surface is handled automatically. The guidelines here apply when you are building a custom container from scratch.Vertical rhythm
The gap between items is controlled by the--bq-option-group--gapY-list CSS custom property. The default is tight (var(--bq-spacing-xs)) to keep the list compact. Increase it only when items are taller than a single text line or when the list is used in a context with generous surrounding whitespace.
Accessible label
TheariaLabel prop (rendered as aria-label on the host element) names the listbox for screen readers. The default value is "Options". Override it with a more specific label when the context makes the default ambiguous — for example, "Navigation links" or "Assignees".
Usage
Flat list
A simple list with no groups. Eachbq-option carries a value so the parent can identify the selection via the bqSelect event.
Options
Custom accessible label
Overridearia-label when the default "Options" is too generic for the context. A specific label helps screen reader users understand the purpose of the list before navigating into it.
Best practices
DoAlways place
bq-option and bq-option-group directly inside bq-option-list — the component listens for bqClick and bqEnter events from child options and will not receive them if additional wrapper elements break the event path.Don’tWrap options in arbitrary
<div> or <span> elements inside the list. Non-option wrappers break the bqClick/bqEnter event delegation that bq-option-list relies on to emit bqSelect.DoOverride
aria-label with a descriptive phrase when the list is not the only role="listbox" on the page or when the default "Options" does not communicate the list’s purpose.Don’tLeave the default
aria-label="Options" on multiple lists within the same view without making each one contextually unique — screen reader users navigating by landmark will see identical labels and cannot tell the lists apart.DoListen to the
bqSelect event on bq-option-list rather than individual bqClick events on each bq-option. The list normalises both click and Enter-key activations into a single bqSelect event with a consistent { value, item } payload.Don’tAttach separate
bqClick listeners to every bq-option when you only need the selected value — bq-option-list already aggregates these and emitting redundant handlers increases the chance of inconsistent state.DoUse
bq-option-group to divide a long list into named sections when the number of items makes scanning difficult.Don’tRender dozens of flat options without any grouping. An ungrouped list longer than around eight items becomes hard to scan — users have to read every item individually rather than jumping to the relevant category.
Accessibility
bq-option-list sets role="listbox" on its host element during componentDidLoad. This establishes the ARIA container that child bq-option elements (which carry role="option") require in order to form a valid accessible list.
The ariaLabel prop is reflected as aria-label on the host and defaults to "Options". It names the listbox for assistive technologies.
As a developer, you are responsible for:
- Providing a meaningful
ariaLabelwhen the default is ambiguous. Screen readers announce the listbox name before a user navigates into it, so a specific label (“Assignees”, “Color palette”) is more useful than the generic default. - Placing only
bq-optionandbq-option-groupelements inside the list — inserting non-option elements breaks therole="listbox"/role="option"relationship that assistive technologies expect. - Managing focus when the list is shown or hidden —
bq-option-listdoes not manage focus automatically. If you are building a custom dropdown, move focus to the first option when the list opens and return it to the trigger when it closes.
API reference
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
ariaLabel | aria-label | Accessible label for the listbox | string | 'Options' |
Events
| Event | Description | Type |
|---|---|---|
bqSelect | Emitted when an option is selected via click or Enter key | CustomEvent<{ value: string; item: HTMLBqOptionElement }> |
Slots
| Slot | Description |
|---|---|
| (default) | bq-option and bq-option-group items |
Shadow parts
| Part | Description |
|---|---|
base | The internal <div> wrapper that stacks slotted items vertically |
CSS custom properties
| Variable | Description | Default |
|---|---|---|
--bq-option-group--gapY-list | Vertical gap between items in the list | var(--bq-spacing-xs) |
Resources
Interactive playground
Explore option list variants and states in Storybook
Source code
View the component source on GitHub