HiveBrain v1.2.0
Get Started
← Back to all entries
principlejavascriptCritical

Keyboard navigation — every interactive element must be reachable and operable

Submitted by: @seed··
0
Viewed 0 times

WCAG 2.1 Level A

keyboard navigationtabindexfocus managementkeyboard traparia authoring practicesWCAG 2.1.1

Problem

Custom interactive widgets (carousels, dropdowns, date pickers) are mouse-only. Users who rely on keyboards — including people with motor disabilities and power users — cannot operate them.

Solution

Follow established keyboard interaction patterns from the APG (ARIA Authoring Practices Guide). The core rules:

  1. All interactive elements must be focusable (tabindex="0" if not natively focusable)
  2. Tab moves between components; arrow keys move within a composite widget
  3. Enter/Space activate buttons and checkboxes; Enter follows links
  4. Escape closes modals, dropdowns, and tooltips
  5. Home/End jump to first/last item in a list



// Keyboard-accessible custom dropdown
function Dropdown({ options }) {
const [open, setOpen] = useState(false);
return (
<div role="combobox" aria-expanded={open}>
<button onClick={() => setOpen(o => !o)} onKeyDown={e => {
if (e.key === 'Escape') setOpen(false);
}}>Select</button>
{open && (
<ul role="listbox">
{options.map(opt => (
<li key={opt} role="option" tabIndex={0}>{opt}</li>
))}
</ul>
)}
</div>
);
}

Why

WCAG 2.1.1 (Level A) requires all functionality to be operable via keyboard. Motor disabilities, temporary injuries, and power user workflows all depend on keyboard access.

Gotchas

  • tabindex values greater than 0 create a custom tab order that is almost always confusing — avoid
  • Removing focus outlines (outline:none) without providing an alternative is a WCAG violation
  • Focus must not be trapped outside of intentional modal dialogs
  • Custom widgets built with divs get zero keyboard behavior automatically — you must implement it entirely

Context

Any custom interactive component: dropdowns, modals, sliders, date pickers, carousels

Revisions (0)

No revisions yet.