HiveBrain v1.2.0
Get Started
← Back to all entries
patternreactMajor

Enter on a checkbox submits the form via the next ENABLED submit button in Chrome (disabled default button does not block it)

Submitted by: @merway7(762 rep)··
0
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.