Our team in Mexico just started doing structured keyboard-only testing as part of our accessibility regression suite. We’re covering the obvious stuff — Tab order, Enter/Space on buttons, Escape to close modals.
But I keep feeling like we’re missing things. Would love to crowdsource a more complete checklist from people who do this regularly.
Here’s what we currently check:
- All interactive elements reachable via
Tab/Shift+Tab - Visible focus indicator present at all times
- Forms submittable without a mouse
- Modals trap focus correctly and return focus on close
- Skip navigation link present and functional
- Dropdowns operable with arrow keys
What are we missing?
Particularly interested in edge cases around:
- Single page app routing — focus management when the “page” changes
- Custom components like date pickers and data tables
- Toast/notification interactions
Good list. A few things I’d add from our testing standards in indonesia:
- Timeout warnings — if your app has session timeouts, can a keyboard user dismiss the warning and extend the session in time?
- Drag and drop alternatives — anything with drag-and-drop UI needs a keyboard-accessible alternative. Often completely forgotten.
- Autocomplete/combobox patterns — these are notoriously broken. Test whether results can be navigated with arrow keys and selected with Enter.
thank you this is useful - thanks @perangkat_lunak also!
For SPA routing specifically — the accepted pattern is moving focus to either the new page
<h1>or a skip link after navigation. Most teams just… don’t do this. It’s a significant failure for screen reader users but keyboard-only users are also affected.
The one that gets missed most often in my experience: focus returning correctly after a dynamic UI change.
Close a modal → focus goes to the button that opened it ✅ Submit a form and get a validation error → focus moves to the error summary ✅ Delete an item from a list → focus goes… somewhere reasonable ✅
That last one is where it usually falls apart. What’s “somewhere reasonable” requires a judgment call and devs rarely think about it.
Also:
pointer-events: noneandvisibility: hiddendon’t always remove elements from tab order the way devs think they do. Worth explicitly testing hidden/off-screen content isn’t focusable.
