When tabbing to an element automatically triggers navigation, form submission, or a dialog, keyboard users lose control over when actions happen. WCAG 2.2 SC 3.2.1 (On Focus) is a Level A requirement: receiving focus must never automatically cause a context change. Users with motor disabilities who accidentally land on a focusable element before their intended target will trigger unintended actions — potentially submitting forms or navigating away from work in progress.
Low because focus-triggered navigation is only a violation when `onFocus` handlers explicitly cause context changes — the default HTML behavior is safe, so scope is limited to explicit misuse of the event.
Remove onFocus handlers that trigger navigation or submission. Separate the display of options from their activation — selection should require an explicit action like clicking a button.
// Bad — navigates on focus, no user confirmation
<select onFocus={(e) => router.push(e.target.value)}>
<option value="/">Home</option>
<option value="/settings">Settings</option>
</select>
// Good — selection updates state; navigation requires an explicit action
<select value={dest} onChange={(e) => setDest(e.target.value)}>
<option value="/">Home</option>
<option value="/settings">Settings</option>
</select>
<button onClick={() => router.push(dest)}>Go</button>
Search the codebase for onFocus event handlers. Any that call router.push, window.location, or form.submit are WCAG 2.2 SC 3.2.1 violations.
ID: accessibility-wcag.understandable.focus-change
Severity: low
What to look for: Enumerate every relevant item. Keyboard-navigate through the page. Check for any elements that submit forms, navigate to a different page, or open dialogs purely from receiving focus (without an explicit Enter or Space key). Look specifically for onFocus event handlers that trigger navigation or form submission. The default behavior of HTML elements (receiving focus does nothing by default) is a pass.
Pass criteria: At least 1 of the following conditions is met. Receiving focus does not trigger navigation, form submission, or unexpected dialogs. Interactions require explicit user action (Enter, Space, or click). Applications with no onFocus event handlers that trigger side effects pass by default.
Fail criteria: An onFocus handler explicitly navigates, submits a form, or opens a dialog when an element receives keyboard focus without user intent.
Skip (N/A) when: Never — focus change behavior applies to all interactive elements.
Detail on fail: Example: "Tabbing to a dropdown menu automatically opens it without user pressing Enter. Link in footer navigates on focus without click"
Remediation: Separate focus from interaction:
// Bad
<select onChange={(e) => navigate(e.target.value)}>
<option value="/">Home</option>
<option value="/about">About</option>
</select>
// Good
<select value={selectedPath}>
<option value="/">Home</option>
<option value="/about">About</option>
</select>
<button onClick={() => navigate(selectedPath)}>Go</button>