Selecting a checkbox, radio button, or dropdown option that immediately submits a form or navigates to another page surprises all users — but disproportionately harms keyboard users who may activate controls while scanning options rather than making a final choice. WCAG 2.2 SC 3.2.2 (On Input) is a Level A requirement: changing a form control's value must not automatically cause a context change without warning the user first.
Low because `onChange`-triggered navigation is only a violation when it directly causes context changes without an explicit submit action — standard controlled state updates do not violate WCAG 2.2 SC 3.2.2.
Keep onChange handlers limited to state updates. Require an explicit user action — clicking a Submit or Apply button — before navigating or submitting.
// Bad — selects a filter and immediately navigates
<select onChange={(e) => router.push(`/results?filter=${e.target.value}`)}>
<option value="recent">Most recent</option>
<option value="popular">Most popular</option>
</select>
// Good — updates state; user applies manually
<select value={filter} onChange={(e) => setFilter(e.target.value)}>
<option value="recent">Most recent</option>
<option value="popular">Most popular</option>
</select>
<button onClick={() => router.push(`/results?filter=${filter}`)}>Apply filter</button>
If instant filtering is a UX requirement, debounce the update by at least 300ms and announce the result count change via aria-live="polite" so users know the page has updated.
ID: accessibility-wcag.understandable.form-change
Severity: low
What to look for: Enumerate every relevant item. Use form controls like checkboxes, radio buttons, select dropdowns. Change their values and check that no form submission or navigation occurs without explicit action. Look for onChange handlers on <select> or <input> elements that call router.push(), window.location.href, or form.submit() directly. Standard onChange handlers that only update state pass by default.
Pass criteria: At least 1 of the following conditions is met. Changing a form control value does not submit the form or navigate. Submission requires an explicit action (click a button). Applications where onChange only updates state (e.g., setFilters(e.target.value)) pass this check.
Fail criteria: An onChange handler on a checkbox, select, or radio button directly triggers form submission or navigation without an explicit submit button click.
Skip (N/A) when: The project has no form controls.
Detail on fail: Example: "Selecting a filter checkbox automatically applies the filter and navigates. Form submits on radio button change without submit button click"
Remediation: Use onChange to update state, not submit:
// Good
<select value={filters} onChange={(e) => setFilters(e.target.value)}>
{/* options */}
</select>
<button onClick={() => applyFilters()}>Apply</button>
// Or use onChange with debounce if auto-apply is needed
useEffect(() => {
const timer = debounce(() => applyFilters(), 300)
return () => clearTimeout(timer)
}, [filters])