patternreactMajor
Enter on a checkbox submits the form via the next ENABLED submit button in Chrome (disabled default button does not block it)
Viewed 0 times
Chromium-based browsers (seen on Chrome 156)
implicit submissioncheckbox enterdefault buttondialog confirmation bypasskeydown preventDefault
browser
Problem
A form holds row checkboxes and, inside closed modal dialogs, destructive submit buttons ("Delete", "Remove"). Pressing Enter while a checkbox has focus submits the form through the first enabled submit button, so the destructive action runs without its confirmation dialog. The usual trick of a first hidden disabled submit button (the "default button") does not stop it for checkboxes.
Solution
Block Enter on checkboxes with a native keydown listener on the form: if e.key === "Enter" and the target is an input of type checkbox, call e.preventDefault() (implicit submission is triggered by the keypress that follows keydown). In React server-rendered forms, mount a tiny client component inside the form that attaches the listener to closest("form") in useEffect and removes it on cleanup. Keep the disabled-default-button trick only for text fields.
Why
Chromium's implicit submission only stops at a disabled default button when the focused control can itself trigger implicit submission (text-like inputs). For a checkbox it skips disabled submit buttons and clicks the first enabled one, even if it sits in a closed dialog.
Gotchas
- Verify with a real key event in the browser: a unit test of the disabled button passes while Chrome still submits.
- The listener only works after hydration; before that the native behaviour applies.
Code Snippets
Client component placed inside the form
export function NoEnterSubmit() {
const ref = useRef<HTMLSpanElement>(null);
useEffect(() => {
const form = ref.current?.closest("form");
if (!form) return;
const block = (e: KeyboardEvent) => {
const t = e.target as HTMLInputElement | null;
if (e.key === "Enter" && t?.tagName === "INPUT" && t.type === "checkbox") e.preventDefault();
};
form.addEventListener("keydown", block);
return () => form.removeEventListener("keydown", block);
}, []);
return <span ref={ref} hidden />;
}Context
Bulk-selection tables whose action buttons live in <dialog> elements inside the same form; keyboard users pressing Enter on a row checkbox.
Revisions (0)
No revisions yet.