<label for="city">City</label>
<input id="city" role="combobox" aria-expanded="true"
aria-controls="city-list" aria-autocomplete="list"
aria-activedescendant="city-2">
<ul id="city-list" role="listbox">
<li id="city-1" role="option">Cairo</li>
<li id="city-2" role="option" aria-selected="true">Casablanca</li>
</ul>
<div role="status" class="visually-hidden">2 results</div>
A combobox is a text input with a popup list of suggestions. It follows the ARIA Authoring Practices combobox pattern.
Markup:
- The input has a real
<label>androle="combobox". aria-expandedsays whether the list is open.aria-controlspoints to the list.aria-autocomplete="list"says suggestions appear as you type.- The list has
role="listbox". Each suggestion hasrole="option"and anid.
Focus: real focus stays in the input, so the user can keep typing. When they arrow through options, aria-activedescendant on the input points to the highlighted option's id. The screen reader reads that option. The highlighted option also gets aria-selected="true".
Keyboard:
- Down Arrow opens the list and moves through options. Up Arrow moves back.
- Enter picks the highlighted option and closes the list.
- Escape closes the list. Pressing it again may clear the input.
Extras:
- Announce the result count in a polite live region, such as "5 results".
- Debounce requests so the announcements don't flood.
- Show a visible highlight for the active option.
This is hard to get right. Consider a tested library such as Downshift, React Aria or Headless UI.
- The input has a label,
role="combobox",aria-expandedandaria-controls. - The popup is a
role="listbox"withrole="option"items. - Focus stays in the input, and
aria-activedescendantpoints to the highlighted option. - Arrow keys move through options, Enter selects and Escape closes.
- The result count is announced in a polite live region.