Combobox
Pair .re-combobox with .re-input on a text input linked to a
<datalist> via the list attribute. Filtering, keyboard navigation, and
the suggestion popup are all provided by the browser — .re-combobox adds
the same chevron as .re-select and suppresses the browser’s own picker
indicator, so the field looks like a select in every state.
The suggestion popup itself is native browser UI: its width, alignment, and theme follow the browser, not your CSS — Chrome sizes it to the suggestion text rather than the input. If you need a popup that matches the input’s geometry and styling, that’s a custom listbox, and free-form suggestions are usually not worth trading for the native filtering, keyboard, and screen reader behavior you’d have to rebuild.
<label class="re-field">
<span class="re-field__label">Favorite fruit</span>
<input
type="text"
class="re-input re-combobox"
list="fruit-options"
placeholder="Start typing…"
/>
</label>
<datalist id="fruit-options">
<option value="Apple"></option>
<option value="Banana"></option>
<option value="Cherry"></option>
<option value="Mango"></option>
<option value="Peach"></option>
<option value="Pear"></option>
</datalist> data-size works the same as on .re-input.
<label class="re-field">
<span class="re-field__label">Small</span>
<input type="text" class="re-input re-combobox" data-size="sm" list="city-options" />
</label>
<label class="re-field">
<span class="re-field__label">Large</span>
<input type="text" class="re-input re-combobox" data-size="lg" list="city-options" />
</label>
<datalist id="city-options">
<option value="Budapest"></option>
<option value="Berlin"></option>
<option value="Lisbon"></option>
</datalist> Enhanced
Section titled “Enhanced”The native popup’s geometry can’t be controlled — Chrome sizes it to the
suggestion text, not the input. If you need a list that is never narrower
than the input (and styled to match your theme), opt into the
enhanceCombobox behavior by adding data-re-combobox:
import { enhanceCombobox } from "@relements/core";enhanceCombobox(document);The same <datalist> stays the data source, so the markup works natively
without JavaScript (and in engines without the Popover API, where the
enhancement steps aside). Enhancing swaps the native popup for a styled
role="listbox": typing filters case-insensitively, Arrow keys move the
highlight, Enter commits, Escape closes; focus never leaves the input
(aria-activedescendant). Committing sets the value and fires input and
change, so frameworks see it like typing.
<label class="re-field">
<span class="re-field__label">Time zone</span>
<input
type="text"
class="re-input re-combobox"
list="zone-options"
data-re-combobox
placeholder="Type to filter…"
/>
</label>
<datalist id="zone-options">
<option value="Europe/Budapest"></option>
<option value="Europe/Berlin"></option>
<option value="Europe/Lisbon"></option>
<option value="America/Argentina/Buenos_Aires"></option>
<option value="America/New_York"></option>
<option value="Asia/Tokyo"></option>
<option value="Australia/Lord_Howe"></option>
</datalist> Accessibility
Section titled “Accessibility”The base combobox is a native <input> linked to a <datalist>, so filtering,
the suggestion popup, and its keyboard model are the browser’s — assistive tech
announces the field, its label, and the native suggestions without any added
role or aria-*. The notes below split the native base from the optional
enhanceCombobox overlay.
- Keyboard — base: native. Tab moves focus in and out, typing filters the
datalist, and the browser’s own keys open and navigate the suggestion popup.
Enhanced: the input becomes an editable combobox — typing filters
(case-insensitive substring) and opens the list,
ArrowDown/ArrowUpopen it (if closed) and move the highlight (wrapping at the ends),Entercommits the highlighted option,Escapecloses the list, andTabcloses it and moves on. Committing sets the value and firesinputandchange, so frameworks observe it like typing. - Focus — focus never leaves the input. In the enhanced mode the highlighted
option is tracked with
aria-activedescendant(no roving focus on the list). The input shows the.re-input:focus-visiblering (--re-shadow-focus, border recoloured to--re-color-focus-ring); setaria-invalid="true"to recolour the border to--re-color-danger-border, announced as invalid. - Semantics — wrap the input in
<label class="re-field">with a.re-field__labelspan (as the demos do) so the label is associated by containment. Enhancing setsrole="combobox",aria-autocomplete="list",aria-expanded, andaria-controlson the input, renders arole="listbox"withrole="option"children, and marks the active optionaria-selected="true"— the editable-combobox pattern. The chevron is a CSS background image and the browser’s native picker indicator is suppressed, so neither is announced. - Notes — because the active option has no real DOM focus, the
aria-selectedhighlight (--re-color-bg-muted) flattens under forced colors; the active option is re-cued with the systemHighlight/HighlightTextcolors so the selection survives Windows High Contrast Mode. Without JavaScript — or in engines without the Popover API — the enhancement steps aside and the fully operable native datalist remains. See the field and select pages and the accessibility guide.