Recipe
Keyboard Trap Detection & Fix
Identify and resolve focus traps that prevent keyboard users from navigating away from a component.
What is a Keyboard Trap?
A keyboard trap occurs when focus becomes locked inside a UI element — a modal, autocomplete, or rich editor — and the user cannot Tab out using standard keyboard navigation. WCAG 2.1 Success Criterion 2.1.2 requires that focus can always be moved away using the keyboard alone.
Detection Checklist
- Tab into every interactive region on the page.
- Attempt to Tab out — if focus loops back, a trap exists.
- Press Escape — does focus return to a logical prior element?
- Test with screen reader running (NVDA / VoiceOver).
- Verify no invisible focusable elements block the path.
Fix Pattern
// 1. Trap focus only when modal is open
const trapFocus = (e: KeyboardEvent) => {
if (e.key !== "Tab") return;
const focusable = container.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusable[0] as HTMLElement;
const last = focusable[focusable.length - 1] as HTMLElement;
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
};
// 2. Always provide an Escape hatch
const onEscape = (e: KeyboardEvent) => {
if (e.key === "Escape") {
closeModal();
triggerRef.current?.focus(); // return focus
}
};Validation
After applying the fix, re-run the detection checklist. Confirm that Tab and Shift+Tab cycle only within the intended container while the component is active, and that Escape dismisses the component and restores focus to the triggering element.