From 3d5b331bd9e6429ed1c06cb543f78899bd1cbecd Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Mon, 25 May 2026 23:53:20 +0200 Subject: [PATCH] feat(ui): autofocus login fields; keep verification code out of form history MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two-step e-mail login now drops the cursor on each step's primary field as it mounts — the e-mail field on load, the code field once the e-mail step advances — via a small `use:` action. Focusing fires each input's onfocus, which clears the readonly autofill guard, so the field is editable straight away. The code input now requests `autocomplete="one-time-code"` instead of `new-password`. The latter is a password-manager hint and does not stop Firefox saving the typed code to form history (it was offering the previous code back in a dropdown). `one-time-code` is the semantic token for a verification code; Firefox honours it specifically to keep the value out of form history (Mozilla bug 1547294). The e-mail field keeps `new-password` to fend off saved-login autofill. Tests: new Vitest cases assert autofocus on both steps and the code field's `one-time-code` token; a new Playwright case covers the same in Chromium and WebKit (Safari engine). Firefox form history is owner manual-QA — there is no Firefox project in the e2e matrix. Co-Authored-By: Claude Opus 4.7 --- ui/docs/auth-flow.md | 30 ++++++++++++ .../src/lib/screens/login-screen.svelte | 28 +++++++++-- ui/frontend/tests/e2e/auth-flow.spec.ts | 33 +++++++++++++ ui/frontend/tests/login-page.test.ts | 46 +++++++++++++++++++ 4 files changed, 134 insertions(+), 3 deletions(-) diff --git a/ui/docs/auth-flow.md b/ui/docs/auth-flow.md index 15d808b..6a4e1fa 100644 --- a/ui/docs/auth-flow.md +++ b/ui/docs/auth-flow.md @@ -81,6 +81,36 @@ those branches. backend collapse into the same `invalid_request` envelope from the UI's perspective; the gateway does not differentiate them externally. +## Focus and autofill suppression + +The login screen drops the cursor on each step's primary field the +moment it mounts — the e-mail field on load, the code field once the +e-mail step advances — so the user can type without first clicking. +This is wired with a one-line `use:` action that focuses the node on +the next tick. + +Both inputs render `readonly` initially and drop the attribute on +first focus (user-driven or via the autofocus action). Safari ignores +`autocomplete="off"` on login-shaped fields and pops the Keychain +suggester on load, but it never autofills a readonly field, so the +page loads quiet and each field turns editable as soon as it is +focused. + +Autofill intent then differs per field: + +- the **e-mail** field asks for `autocomplete="new-password"` to keep + password managers from injecting a saved login; +- the **code** field asks for `autocomplete="one-time-code"`, the + semantic token for a verification code. It is the reliable way to + keep Firefox from saving the code to form history and offering it + back in a dropdown — Firefox honours that token specifically, while + plain `autocomplete="off"` is not respected for this field + ([Mozilla bug 1547294](https://bugzilla.mozilla.org/show_bug.cgi?id=1547294)). + +Playwright covers the autofocus and the code field's token in WebKit +(Safari engine) and Chromium; Firefox form-history behaviour is +verified by hand, as there is no Firefox project in the e2e matrix. + ## Resend and change-email - **send a new code** — re-issues `sendEmailCode` for the same diff --git a/ui/frontend/src/lib/screens/login-screen.svelte b/ui/frontend/src/lib/screens/login-screen.svelte index 95c20b1..f782191 100644 --- a/ui/frontend/src/lib/screens/login-screen.svelte +++ b/ui/frontend/src/lib/screens/login-screen.svelte @@ -1,4 +1,5 @@