agentsclimarketplace

A11y combobox

Skill xrnavigation/web-a11y-plugin/skills/a11y-combobox

Web accessibility agent skills — 23 cite-backed skills covering APG widget patterns, audit tooling, ARIA guidance, cognitive accessibility, and more. Works with Claude Code, Codex CLI, and Gemini CLI.

Install
npx -y skills add xrnavigation/web-a11y-plugin --skill a11y-combobox

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Guides accessible combobox and autocomplete implementation per APG patterns. Auto-invokes when creating combobox, autocomplete, typeahead, select-with-search, or custom dropdown components. Covers required ARIA, keyboard interaction, and variant selection (select-only, editable, autocomplete modes).

SKILL.md

10.6 KB, as published. Nobody here has run it

Accessible Combobox Implementation

"No ARIA is better than Bad ARIA." — APG Read Me First

A combobox is a composite widget combining a named input with a popup that lets users set the input's value. The popup can be a listbox, grid, tree, or dialog. (APG Combobox Pattern)

This is one of the hardest widgets to get right. Screen reader support is inconsistent, aria-activedescendant is unreliable, and the keyboard interaction surface is large. Read this skill before building.


1. When to Use Native <select> vs Combobox

Use this decision tree before reaching for ARIA combobox.

SituationUseWhy
Single selection, < 15 items, no filtering needed<select>100% AT success rate, 97.5 usability score in testing. (24a11y study)
Simple autocomplete, inconsistent styling acceptable<datalist>Native, but broken on Android Firefox, iOS/iPadOS VoiceOver limited to 3 options. (Roselli)
> 15 options, need type-ahead filtering, closed listSelect-only comboboxCustom styling possible; caveat: WebKit bug with aria-activedescendant in VoiceOver/Safari. (APG)
Free text input + optional suggestionsEditable comboboxSearch, address lookup, autocomplete patterns. (APG)
Multi-select from listAvoid <select multiple>Only 25.3% AT success rate. Use a listbox with checkboxes instead. (24a11y study)

Do NOT use the ARIA 1.1 readonly-input combobox pattern — it is invisible to NVDA scan mode. (24a11y study)


2. Combobox Variants

Autocomplete Modes

Modearia-autocompleteBehavior
No autocompletenonePopup shows fixed suggestions (e.g., recent searches)
List (manual)listPopup filters to matches; user must explicitly select
List (automatic)listFirst match auto-highlighted; becomes value on blur
Inline + listbothFirst match auto-highlighted AND inline completion shown in input

Source: APG Combobox Pattern

Structural Variants

  1. Select-only — No text input; <div role="combobox">. Functionally replaces <select>. (Example)
  2. Editable + autocomplete="both" — Full inline + list filtering. (Example)
  3. Editable + autocomplete="list" — List filtering, manual selection. (Example)
  4. Editable + autocomplete="none" — Fixed suggestion list, no filtering. (Example)
  5. Grid popuprole="grid" popup for tabular suggestions. (Example)
  6. Dialog popuprole="dialog" popup (e.g., date picker). DOM focus moves into dialog. (Example)

3. Required ARIA Structure

Minimal Correct Markup (Editable + Listbox)

<!-- WRONG — missing aria-controls, no listbox role, no option roles -->
<input type="text" role="combobox">
<ul class="dropdown">
  <li>Option 1</li>
</ul>

<!-- RIGHT -->
<label for="fruit-input">Fruit</label>
<input
  id="fruit-input"
  role="combobox"
  type="text"
  aria-expanded="false"
  aria-controls="fruit-listbox"
  aria-autocomplete="list"
  aria-activedescendant=""
>
<ul id="fruit-listbox" role="listbox" hidden>
  <li id="opt-apple" role="option">Apple</li>
  <li id="opt-banana" role="option">Banana</li>
</ul>

Minimal Correct Markup (Select-Only)

<!-- WRONG — using readonly input (ARIA 1.1 pattern, invisible to NVDA scan mode) -->
<input type="text" role="combobox" readonly>

<!-- RIGHT -->
<label id="color-label">Color</label>
<div
  role="combobox"
  tabindex="0"
  aria-labelledby="color-label"
  aria-expanded="false"
  aria-controls="color-listbox"
  aria-haspopup="listbox"
  aria-activedescendant=""
>Red</div>
<ul id="color-listbox" role="listbox" hidden>
  <li id="opt-red" role="option" aria-selected="true">Red</li>
  <li id="opt-blue" role="option">Blue</li>
</ul>

Required Attributes Reference

ElementAttributeValueNotes
ComboboxrolecomboboxOn <input> or <div> (select-only)
Comboboxaria-controlsIDREFMust reference popup; present even when hidden
Comboboxaria-expandedtrue/falseReflects popup visibility
Comboboxaria-autocompletenone/list/bothOmit only if none
Comboboxaria-haspopupgrid/tree/dialogOnly when popup is NOT listbox (default)
Comboboxaria-activedescendantIDREFPoints to focused option; DOM focus stays on combobox
Popuprolelistbox/grid/tree/dialogMust match aria-haspopup
Optionsroleoption/gridcell/treeitemPer popup type
Optionsaria-selectedtrueOn currently focused/selected option

Source: APG Combobox Pattern, WAI-ARIA 1.2


4. Keyboard Interaction Summary

Abbreviated table. Full spec per variant: ${CLAUDE_SKILL_DIR}/references/keyboard-interaction.md

KeyEditable ComboboxSelect-Only (Closed)Select-Only (Open)
Down ArrowOpen popup, focus first/next optionOpen popupNext option
Up ArrowOpen popup (optional), focus lastOpen popupPrevious option
EnterAccept focused option, closeOpen popupAccept option, close
EscapeClose popupClose without selecting
TabMove focus outMove focus outAccept + close + move focus
Printable charsType in inputOpen + jump to matchJump to matching option
Home/EndMove cursor in inputFirst/last option
Alt+DownOpen without moving focusOpen popup

5. Common Mistakes

5.1 Treating aria-activedescendant as DOM Focus

<!-- WRONG — moving DOM focus to each option -->
<input role="combobox" ...>
<ul role="listbox">
  <li role="option" tabindex="0">Apple</li> <!-- Don't make options focusable -->
</ul>

<!-- RIGHT — DOM focus stays on input, aria-activedescendant points to option -->
<input role="combobox" aria-activedescendant="opt-apple" ...>
<ul role="listbox">
  <li id="opt-apple" role="option" aria-selected="true">Apple</li>
</ul>

aria-activedescendant is a screen reader semantic, not focus. Only one element has true focus (document.activeElement). Keyboard events fire on the focused element, not the active descendant. (Higley)

Exception: Dialog popups DO move real DOM focus into the dialog. They do NOT use aria-activedescendant. (APG)

5.2 Relying Solely on aria-activedescendant for Announcements

VoiceOver ignores aria-activedescendant changes when the input is empty (Safari) or when aria-selected="true" is missing (Chrome). NVDA fails to announce character deletions. Mobile screen readers essentially ignore it entirely.

Fix: Supplement with a hidden aria-live region for critical state changes (option count, selected value). React Aria had to adopt this workaround. (React Aria; Higley)

5.3 Using role="group" on Option Groups

<!-- WRONG — VoiceOver fails to announce focus on grouped options -->
<ul role="listbox">
  <li role="group">
    <ul>
      <li role="option">Apple</li>
    </ul>
  </li>
</ul>

<!-- RIGHT — flat list, use aria-label on options if grouping context needed -->
<ul role="listbox">
  <li role="option" aria-label="Fruit: Apple">Apple</li>
</ul>

Source: React Aria

5.4 Missing aria-controls When Popup Is Hidden

aria-controls must reference the popup element even when the popup is not visible. The referenced element must exist in the DOM. (APG Combobox Pattern)

5.5 Adding Screen Reader Control Hints

<!-- WRONG — screen readers already announce how to use a combobox -->
<input role="combobox" aria-description="Use arrow keys to navigate options">

<!-- RIGHT — let the screen reader provide its own instructions -->
<input role="combobox" ...>

Screen readers already tell users how to interact with standard controls. Custom instructions create conflicts, redundancy, and verbosity. (Roselli)

5.6 Auto-filtering Without User Request

The 24a11y study found that auto-filtering options without explicit user opt-in reduced success rates. Show the full list first; filter only on explicit interaction. (24a11y study)


6. Cross-References

  • aria-decision-framework — check whether you need ARIA combobox at all (use native <select> first)
  • ${CLAUDE_SKILL_DIR}/references/keyboard-interaction.md — complete keyboard spec per variant
  • ${CLAUDE_SKILL_DIR}/references/screen-reader-behavior.md — per-AT behavior differences and workarounds
  • ${CLAUDE_SKILL_DIR}/references/common-mistakes.md — expanded anti-patterns with citations
  • ${CLAUDE_SKILL_DIR}/references/sources.yaml — provenance for all cited sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.