← Back to Web app developers
See how it helps
1. Modal & Non-Modal Dialogs (
3. Tabs (
4. Combobox / Autocomplete (
Accessible interactive components
Builds dialogs, menus and other interactive controls with keyboard behavior, meaningful labels and predictable focus management.
accessible-component-development
Team members using this skill
When is it useful?
Use when a custom menu or dialog works with a mouse but blocks keyboard or screen reader users.
What does it help you do?
- Matches each widget's ARIA role to its required keyboard interactions.
- Restores focus after dialogs close and prevents interaction with their background.
- Makes tables, autocomplete options and tooltips understandable beyond mouse hover.
Try asking this
Fix our account menu and confirmation dialog. Check arrow keys, Escape, focus restoration and screen reader names. After cancellation, focus should return to the account button. Opening the dialog must prevent keyboard navigation into the background page.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Accessible Component Development
Custom interactive components fail for keyboard or screen reader users when ARIA attributes are added without implementing their required keyboard and focus state machine. Every ARIA role is a behavioral contract.
1. Modal & Non-Modal Dialogs (dialog / alertdialog)
- Prefer native
<dialog>opened with.showModal(), orrole="dialog"witharia-modal="true". - Name the dialog via
aria-labelledbypointing to its visible title heading; usearia-describedbyonly for short confirmation text (as inrole="alertdialog"), not entire complex forms. - Required behavior:
- Background content is inert (
inerton app root siblings) so neitherTabnor screen reader virtual cursor escapes behind the backdrop. Escapecloses the dialog (unless an explicit unsaved-changes guard intercepts it).- Closing via
Escape, Close button or backdrop restores focus to the trigger element.
- Background content is inert (
2. Disclosure, Accordions, Menus & Popovers
Distinguish between a disclosure (shows/hides arbitrary content) and a menu (an application action list):
- Disclosure / Accordion:
- Trigger is
<button type="button" aria-expanded="true|false" aria-controls="panel-id">(inside<h3><button>...</button></h3>for accordions). - Panel uses normal
Tabnavigation; never putrole="menu"ormenuitemon navigation link groups or filter panels.
- Trigger is
- Action Menu (
role="menu"/menuitem/menuitemcheckbox/menuitemradio):- Trigger button has
aria-haspopup="menu"andaria-expanded="true|false". - Keyboard open (
Enter,Space,ArrowDown) focuses the first enabledmenuitem. ArrowDown/ArrowUpcycles items,Home/Endjumps to first/last, character keys jump by first letter,Escapecloses and restores trigger focus, andTabcloses the menu.
- Trigger button has
3. Tabs (tablist, tab, tabpanel)
- Container has
role="tablist"(aria-label/aria-labelledby, plusaria-orientation="vertical"if vertical). - Each tab is
<button type="button" role="tab">witharia-selected="true|false",aria-controls="panel-id", and rovingtabindex(0on selected,-1on inactive). - Each panel has
role="tabpanel"andaria-labelledby="tab-id", withhiddenon inactive panels. - Arrow keys move between tabs (activating automatically on focus for lightweight panels, or via
Enter/Spacewhen switching triggers heavy network work).
4. Combobox / Autocomplete (role="combobox")
- Text
<input>hasrole="combobox",aria-expanded="true|false",aria-controls="listbox-id",aria-autocomplete="list|both"andaria-activedescendanttracking the highlighted<li role="option" id="...">. - Options reflect selection via
aria-selected="true|false". ArrowDown/ArrowUpnavigates options without losing input cursor position,Enterselects the active option,Escapecloses the popup, and empty states ("No results found") are announced cleanly.
5. Data Tables, Grids & Tooltips
- Tables: use
<table>,<caption>(oraria-labelledby),<th scope="col">and<th scope="row">. For sortable columns, place a<button>inside the<th>and setaria-sort="ascending|descending|none"on the<th>. - Tooltips: a
role="tooltip"linked viaaria-describedbyis for supplementary hints only. It must appear on both:hoverand:focus-visible, stay hoverable, and dismiss onEscapewithout stealing focus (WCAG 1.4.13). Never place interactive controls inside atooltip— use a popover/disclosure instead.
Included files 1
SKILL.md
