Skip to main content

rc-listbox

Listbox that keeps option DOM in light DOM for aria-activedescendant navigation, following the WAI-ARIA Listbox pattern.

rc-listbox is primarily an infrastructure component that can be used directly when an application or component controls option data and selection state.

Package
@rcarls/rc-listbox
Element
<rc-listbox>
Native dependency
<ul>/<li> rendered into the host's light DOM
State model
Controlled or uncontrolled selection
Main events
rc-listbox-change

Installation

npm install @rcarls/rc-listbox
import '@rcarls/rc-listbox/define';

Live demo

Usage

rc-listbox is usually an infrastructure component inside composite controls. Use it directly when application code owns the option data and selection state.

const listbox = document.querySelector('rc-listbox');

listbox.options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'cherry', label: 'Cherry', disabled: true },
];

listbox.setSelectedValues(['apple']);

Action options

Most rows should be selectable options. Rows that perform commands, such as create, clear, or other flows, can use kind: 'action'. The change event is a discriminated union, so event.detail.reason narrows the detail type.

listbox.options = [
{ value: 'apple', label: 'Apple' },
{ kind: 'action', action: 'clear', value: 'clear', label: 'Clear selection' },
];

listbox.addEventListener('rc-listbox-change', (event) => {
if (event.detail.reason === 'action') {
console.log(event.detail.action);
return;
}

console.log(event.detail.option.value, event.detail.selected);
});

Progressive enhancement with pre-rendered markup

Consumers may supply a <ul> with <li> children directly in the component's slot. On first connect, the component reads those elements to bootstrap its internal options. The pre-rendered list is visible and keyboard-navigable before JavaScript runs.

<rc-listbox aria-label="Fruit">
<ul>
<li value="apple">Apple</li>
<li value="banana">Banana</li>
<li value="cherry" disabled>Cherry</li>
</ul>
</rc-listbox>

Once the options property is set at any point, it becomes the authoritative source and the pre-rendered markup is replaced.

Theming

The default mode shows the component without a package theme applied. Use the shared preview controls on this page to compare inherited, light, and dark color schemes, or to apply the optional Material theme inside the demo frame.

Base styles (layout, system-color selection, disabled state) are injected once per root node with a style[data-rc-light-dom-base="rc-listbox"] element in an rc-base cascade layer.

API

Properties

PropertyMarkupTypeDefaultDescription
multiplemultiplebooleanfalseAllow multiple selection. Reflected as `aria-multiselectable` on the host.
checkmarkcheckmarkbooleanfalseRender a checkmark indicator inside each option element. Hidden by default; enable for combobox / select patterns where the consumer's CSS shows it conditionally via `[aria-selected='true']`.
filterStrategyfilter-strategyFilterStrategy'contains'How option labels are matched against the active filter text. Defaults to `'contains'` (substring). Set to `'prefix'` for starts-with matching, or pass a custom predicate for full control. Function values are JS-only; string values may be set via the `filter-strategy` attribute.
allOptionsJS property onlyreadonly ListboxOption[]Not specifiedAll options regardless of filter state.
filteredOptionsJS property onlyreadonly ListboxOption[]Not specifiedOptions currently passing the active filter.
optionsJS property onlyListboxOption[]Not specifiedReplace the full options list.
selectedValuesJS property onlystring[]Not specifiedCurrent selection as a consistently-array-shaped read-only view.
valueJS property onlystring | string[]Not specifiedCurrent selection. Host writes update silently.
defaultValueJS property onlystring | string[] | undefinedNot specifiedInitial uncontrolled selection.
navigableItemsJS property onlyElement[]Not specifiedOrdered list of currently navigable option elements (visible and not disabled). Feed this to `ActiveDescendantController.items` in the parent component. Includes the create option element when one is set.

Methods

MethodDescription
appendOption(option: ListboxOption)Append a single option without replacing the list.
setSelectedValues(values: string[])Replace the selection set without firing `rc-listbox-change`.
toggleOption(value: string)Toggle the selected state of the option with `value`. In single-select mode, toggling a selected item deselects it (and selects the new item). Fires `rc-listbox-change`.
clearSelection()Clears all selected values without firing `rc-listbox-change`.
filterOptions(text: string)Filter visible options to those whose label matches `text` (case-insensitive).
clearFilter()Removes any active filter, making all options visible.
setCreateOption(label: string | null)Show or hide the "Create" option at the end of the list. Pass `null` to hide it, or a non-empty string to show `Create "{label}"`. Fires `rc-listbox-change` with `reason: 'action'` and `action: 'create'` when activated.

Events

EventDetail typeDescription
rc-listbox-changeCustomEventFired when an option is activated (clicked or Enter/Space)

Slots

NameDescription
Accepts pre-rendered `<ul>` with `<li>` children for progressive enhancement.

CSS Custom Properties

PropertyDefaultDescription
--rc-listbox-option-gap0.25remGap between the checkmark and option label.
--rc-listbox-option-min-block-size0pxMinimum block size (height) of each option row.
--rc-listbox-option-padding-block2pxBlock-axis padding of each option row.
--rc-listbox-option-padding-inline4pxInline-axis padding of each option row.
--rc-listbox-option-transitionNot specifiedCSS transition applied to each option row.
--rc-listbox-hover-bgNot specifiedBackground of a hovered option.
--rc-listbox-hover-colorNot specifiedText color of a hovered option.
--rc-listbox-active-bgNot specifiedBackground of the keyboard-active option.
--rc-listbox-active-colorNot specifiedText color of the keyboard-active option.
--rc-listbox-selected-bgNot specifiedBackground of a selected option.
--rc-listbox-selected-colorNot specifiedText color of a selected option.
--rc-listbox-disabled-colorNot specifiedText color of a disabled option.
--rc-listbox-disabled-opacityNot specifiedOpacity of a disabled option.

CSS Parts

PartDescription
optionIndividual `<li role="option">` elements
option-checkmarkThe checkmark `<span>` inside each option (when `checkmark` is true)
create-optionThe "Create" option when allow-create is active