RRenDSv0.13.0

Composite

Combobox Requires JS

A typeahead-searchable picker. Combines a text input with a filtered listbox so users can either type to filter or arrow-key through options. Use it when you have more than ~15 options and need search, but don't need full free-text input (use <input type="text"> with a datalist for that).

About

Overview

Combobox is a Select with a search box on top. The user can either click the trigger to see all options, or start typing to narrow them down. Each keystroke filters the visible items, arrow keys jump between them, Enter picks one. The chosen value is submitted via a hidden input named after the name attribute.

Combobox vs Select vs native select. Use native for short lists where the platform dropdown is fine. Use Select for richer item rendering but no search. Use Combobox when there are too many items to scroll comfortably and the user knows roughly what they want.

Parts

Anatomy

Assembled

1Container

<ren-combobox> wrapper. Manages selection, filtering, and the hidden form value.

2Input

<input role="combobox">. Holds the search query when open, the chosen label when closed.

3Listbox

role="listbox" popover with the visible (filtered) items. Hides items that don't match the query.

4Item

.ren-combobox-item with role="option" and a data-value. Filtering matches against the visible text.

Live

Demo

Argentina
Brazil
Chile
Colombia
Ecuador
Mexico
Peru
United States
Uruguay
<ren-combobox name="country" placeholder="Search a country…">
  <div class="ren-combobox-item" data-value="ar">Argentina</div>
  <div class="ren-combobox-item" data-value="br">Brazil</div>
  <div class="ren-combobox-item" data-value="cl">Chile</div>
  …
</ren-combobox>

Shapes

Variants

With descriptions

Items can hold structured content — a primary line and a muted secondary line. Useful for "User name + email" or "Repo name + organization" patterns.

Grouped

Wrap related items in .ren-combobox-group with an optional .ren-combobox-group-label. Filtering keeps the group label visible while any of its items match.

Async loading

Listen for ren-search and replace the items as the user types. Show .ren-combobox-loading while a request is in flight.

Reference

API

CSS classes

ClassEffect
.ren-comboboxWrapper. Sets up positioning context for the floating list.
.ren-combobox-inputThe text input. role="combobox", aria-autocomplete="list".
.ren-combobox-listThe listbox popover. Shows below the input on open.
.ren-combobox-itemOne option. Use with role="option" and data-value.
.ren-combobox-group / -group-labelOptional grouping for items.
.ren-combobox-empty"No results" message shown when the filter matches nothing.
.ren-combobox-loadingLoading row for async data.

Web Component attributes

AttributeTypeDefaultNotes
namestringForm field name. Submitted via a hidden input.
valuestringInitial selected data-value.
placeholderstring"Search..."Empty-state text in the input.
placement"top" | "bottom""bottom"Preferred side for the local list. Reflected to data-side; top opens above the input.
disabledbooleanfalseLocks the input.
asyncbooleanfalseIf present, suppresses local filtering — the parent app provides items via ren-search.

Events

EventDetail
ren-changeSelection changed. { value, item }. Bubbles, composed.
ren-searchUser typed. { query }. Use this for async loading. Bubbles.
ren-open / ren-closeListbox opened / closed. Bubbles, composed.

JavaScript methods

MethodReturnsArgsNotes
.value string Getter / setter for the selected data-value. Setting it updates the input and dispatches ren-change.
.open() void Programmatically opens the listbox.
.close() void Programmatically closes the listbox.
.setLoading(state) void boolean Toggles the .ren-combobox-loading row. Pair with ren-search to indicate an async fetch is in flight.
.setItems(items) void Array<{value, label, description?}> Replaces the visible options. Use with the async attribute when the parent app owns filtering.

Inclusive by default

Accessibility

Keyboard

Opens the list, highlights the first match.
/ Navigate the visible items.
EnterSelect the highlighted item.
EscCloses the list. Press again to clear the input.
TypeFilters the items. Filtering is case-insensitive substring match by default.

Labelling

Wrap inside Form Field, or set aria-label on the input. Don't use the placeholder as a label.

Always handle the empty state. When filtering yields zero items, show .ren-combobox-empty. Silence is worse than "No results — try a different word".

Patterns

Examples

Async loading

const combo = document.querySelector('ren-combobox[async]'); combo.addEventListener('ren-search', async (e) => { combo.setLoading(true); const results = await fetch(`/api/users?q=${encodeURIComponent(e.detail.query)}`).then(r => r.json()); combo.setItems(results.map(u => ({ value: u.id, label: u.name, description: u.email }))); combo.setLoading(false); });

Pre-selecting

<ren-combobox name="country" value="ar"> <div class="ren-combobox-item" data-value="ar">Argentina</div> <div class="ren-combobox-item" data-value="br">Brazil</div> </ren-combobox>