Build an accessible ARIA widget
Implements a combobox, tabs, dialog, menu, disclosure, tree or listbox per the ARIA Authoring Practices pattern, using native elements whenever they suffice. Use for custom interactive widgets.
The first rule of ARIA is not to use it when a native element does the job: WebAIM's yearly scans of the top million home pages keep finding more errors on pages that use ARIA than on pages that do not. When a custom widget is justified, it has to match the APG pattern exactly: the roles, the states that update as the user acts, and the keyboard model screen-reader users already know from desktop apps. Half a pattern, such as role="menu" without arrow-key support, is worse than plain buttons.
Build an accessible in .
Existing code or usage: (if empty, build from scratch with a minimal, typical API).
- Decide native or custom first, and state the decision:
- dialog: use
dialogwithshowModal(). It provides the top layer, an inert background and Escape for free. - disclosure: use
detailsandsummary, or abuttonwitharia-expandedandaria-controls. - listbox: use
selectunless options need rich content or multi-select with custom rendering. - menu:
role="menu"is for app-style command menus. For site navigation or a list of links, build a disclosure with links instead, and say so. - combobox: a text
inputwith a custom popup.datalistis acceptable only for simple suggestions. - tabs and tree have no native equivalent, so build them custom.
- If custom, implement the APG pattern completely:
- The roles and their required owned elements (
tablistandtabwithtabpanel;tree,treeitemandgroup;comboboxandlistboxwithoption). - States kept in sync with the UI:
aria-expanded,aria-selected,aria-checked,aria-activedescendant,aria-controls, andaria-level,aria-setsizeandaria-posinsetwhen items are virtualised. - Accessible names for the widget and each item.
- One Tab stop for composite widgets, using roving
tabindexoraria-activedescendant, with the APG keyboard model: arrow keys, Home and End, Escape, Enter and Space, and type-ahead where the pattern specifies it. - Focus management on open and close: where focus goes, and where it returns.
- For tabs, choose automatic or manual activation and justify it (manual when showing a panel is slow). For combobox, implement the ARIA 1.2 pattern, where
role="combobox"sits on the input itself andaria-autocompletematches the actual behaviour. - Reuse the project's existing components and styles. Make focus visible.
- Write tests that query by role and accessible name (Testing Library style or the framework's equivalent), assert state attributes after interactions, and drive the keyboard model.
- Do not add ARIA that duplicates native semantics, such as
role="button"on abutton. - Do not use
aria-hidden="true"on anything focusable. - If is the wrong pattern for the described use, say so, recommend the right one, and build that instead.
- Read the relevant code before making a claim about it. Do not guess what a file, function or config contains.
- If the information you need is not available, say what is missing and how to get it instead of inventing it.
Native or custom
The decision and why, in two or three sentences.
Keyboard
| Key | Context | Result |
Roles states and properties
| Element | Role | Attributes and when they change |
Code
Each file in its own code block, headed by its path.
Tests
Code, then one line per test.
Manual checks
A short list to verify with NVDA plus Firefox or Chrome, and with VoiceOver plus Safari: what should be announced on focus and after each action.
1 required value still a placeholder; the assistant will ask for it.
details
- kind
- Prompt: a task you run by name to get one finished thing back
- domain
- Software engineering
- category
- Accessibility
- level
- Expert
- made for
- Frontend engineer, Full-stack engineer
- needs
- repo-read, file-write
- risk
- edits-files
- version
- v1.0.0 · incubating
- reviewed
- 2026-10-02
- works in
- Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md
use in
npx @hermes-hq/hodios install build-aria-widget --target claude-codenpx skills add hermes-hq/hodios-dist --skill build-aria-widget -a claude-codeclaude plugin marketplace add hermes-hq/hodios-distclaude plugin install hodios-software-engineering@hodiosThe plugin brings every entry in this domain at once.
pairs well with
All of AccessibilityAccessibility specialist
Accessibility specialist who builds and reviews with WCAG, the ARIA Authoring Practices and real assistive-technology behaviour in mind, ranking barriers by who is blocked.
accessibility-specialistFix keyboard navigation in a component
Finds and fixes keyboard barriers in a UI component (focus order, traps, invisible focus, mouse-only controls) and adds a keyboard test checklist. Use when a widget fails without a mouse.
fix-keyboard-navigationWrite a screen-reader test plan
Writes a manual screen-reader test script for a user flow on NVDA, JAWS, VoiceOver or TalkBack, with keystrokes and expected announcements per step. Use before releasing a key flow.
write-screen-reader-test-planAudit a mobile screen for accessibility
Audits an iOS, Android, React Native or Flutter screen for labels, traits, focus order, text scaling, touch targets, contrast and gestures, with platform fixes and a VoiceOver or TalkBack test script.
audit-mobile-accessibilityAudit web accessibility against WCAG 2.2
Audits markup or components against WCAG 2.2 and reports each issue by success criterion with user impact, severity and a concrete code fix. Use before a release or a compliance review.
audit-web-accessibilityBuild or fix an accessible form
Builds or repairs a web form with programmatic labels, grouping, autocomplete, helpful error messages and announced validation. Use for sign-up, checkout, settings or any data-entry form.
fix-form-accessibility