Pressing Enter in the Poll, Schedule or Report dialogs closes them and throws away what you typed (the header ✕ is the form's default submit button) #315

Open
opened 2026-10-05 01:40:41 -04:00 by jared · 0 comments
Owner

Several fork dialogs are <Box as="form" onSubmit=…> with the header close button inside the form. folds' IconButton renders a <button> with no type, so it is a submit button, and it comes first in the form. On implicit submission, pressing Enter in a text field "clicks" the form's first submit button. Here that's ✕, whose onClick closes the dialog.

Measured (Playwright):

Dialog Action Result
Create Poll (PollCreator.tsx) type "Where should we eat?" in the question, press Enter dialog closes, poll discarded, nothing sent
Schedule Message (ScheduleMessageModal.tsx) press Enter in the time field dialog closes, nothing scheduled
Report User (ReportUserModal.tsx) type a reason, press Enter dialog closes, no report request (clicking Report User works: POST /users/@aud_bob:localhost/report {"reason":"[Spam] …"} → 200)
Report Room (ReportRoomModal.tsx) same structure same code path, not run

The Report User controls in DOM order are BUTTON[type=submit] Close, BUTTON[type=button] Spam, INPUT reasonInput, BUTTON[type=submit] Report User.

Enter-to-submit is the natural move in a one-field dialog ("type reason ⏎"). Here it silently discards the input, and for polls it throws away a question and all its answers.

Fix: give every header/close IconButton inside a form type="button". Or move the header outside the <form> and use a form="…" attribute on the submit button. A lint rule would stop it coming back (e.g. react/button-has-type, or a small custom rule for IconButton inside as="form").

A static scan finds the same pattern in some upstream files: components/AccountDataEditor.tsx, features/common-settings/developer-tools/StateEventEditor.tsx, components/DeviceVerificationSetup.tsx, and a dialog in features/room/message/Message.tsx. I didn't exercise those; worth the same one-word fix (and an upstream PR).

Also verified in this pass: a private note on a user profile saves to io.lotus.user_notes and survives a reload.


Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny 30e2dbcd, cinny-desktop 8f67ec7, element-call 3b0050e8.

Several fork dialogs are `<Box as="form" onSubmit=…>` with the header close button **inside** the form. folds' `IconButton` renders a `<button>` with no `type`, so it is a **submit** button, and it comes first in the form. On implicit submission, pressing Enter in a text field "clicks" the form's first submit button. Here that's ✕, whose `onClick` closes the dialog. **Measured (Playwright):** | Dialog | Action | Result | |---|---|---| | **Create Poll** (`PollCreator.tsx`) | type "Where should we eat?" in the question, press Enter | dialog closes, **poll discarded**, nothing sent | | **Schedule Message** (`ScheduleMessageModal.tsx`) | press Enter in the time field | dialog closes, **nothing scheduled** | | **Report User** (`ReportUserModal.tsx`) | type a reason, press Enter | dialog closes, **no report request** (clicking **Report User** works: `POST /users/@aud_bob:localhost/report {"reason":"[Spam] …"}` → 200) | | **Report Room** (`ReportRoomModal.tsx`) | same structure | same code path, not run | The Report User controls in DOM order are `BUTTON[type=submit] Close`, `BUTTON[type=button] Spam`, `INPUT reasonInput`, `BUTTON[type=submit] Report User`. Enter-to-submit is the natural move in a one-field dialog ("type reason ⏎"). Here it silently discards the input, and for polls it throws away a question and all its answers. **Fix:** give every header/close `IconButton` inside a form `type="button"`. Or move the header outside the `<form>` and use a `form="…"` attribute on the submit button. A lint rule would stop it coming back (e.g. `react/button-has-type`, or a small custom rule for `IconButton` inside `as="form"`). A static scan finds the same pattern in some upstream files: `components/AccountDataEditor.tsx`, `features/common-settings/developer-tools/StateEventEditor.tsx`, `components/DeviceVerificationSetup.tsx`, and a dialog in `features/room/message/Message.tsx`. I didn't exercise those; worth the same one-word fix (and an upstream PR). Also verified in this pass: a private note on a user profile saves to `io.lotus.user_notes` and survives a reload. --- _Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny `30e2dbcd`, cinny-desktop `8f67ec7`, element-call `3b0050e8`._
jared added the bugpriority: mediumarea: messaging labels 2026-10-05 01:40:41 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#315