From be50f1442148c21cabf039abdcae5fe20bc690e8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sun, 20 Sep 2026 16:35:46 +0200 Subject: feat(hub): reveal button in the sign-in and registration passphrase fields One PasswordInput for all three fields, with an eye toggle inside the box. Out of the tab order, type="button" so a click cannot submit the form. Co-Authored-By: Claude Opus 5 --- .../src/meshbay_hub/static/auth-page.js | 47 +++++++++++++++++----- .../meshbay-hub/src/meshbay_hub/static/icon.js | 6 +++ .../src/meshbay_hub/static/locales/de.js | 2 + .../src/meshbay_hub/static/locales/en.js | 2 + .../src/meshbay_hub/static/locales/es.js | 2 + .../src/meshbay_hub/static/locales/fr.js | 2 + .../src/meshbay_hub/static/locales/it.js | 2 + .../src/meshbay_hub/static/locales/ja.js | 2 + .../src/meshbay_hub/static/locales/nl.js | 2 + .../src/meshbay_hub/static/locales/pl.js | 2 + .../src/meshbay_hub/static/locales/pt-BR.js | 2 + .../src/meshbay_hub/static/locales/zh-CN.js | 2 + .../meshbay-hub/src/meshbay_hub/static/style.css | 26 ++++++++++++ 13 files changed, 90 insertions(+), 9 deletions(-) (limited to 'packages/meshbay-hub') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js b/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js index 8958d44..f0af187 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js @@ -14,6 +14,35 @@ const PASSWORD_MIN_LEN = 12; // before a passphrase derivation rather than after it. const USERNAME_MIN_LEN = 8; +// ── Passphrase field ───────────────────────────────────────────────────────── +// +// A passphrase this long is mistyped often enough that checking it is worth a +// control, and the alternative people reach for otherwise is typing it into +// the username box to read it back. The button is out of the tab order +// (`tabindex="-1"`): everyone who is not reaching for it would pay a keystroke +// between the passphrase and the submit button, and it does nothing a keyboard +// user cannot do by other means. `type="button"` matters — a bare button in a +// form submits it, which here would try to sign in on the first click. +function PasswordInput({ + value, onInput, placeholder, autocomplete, + minlength = null, autofocus = false, +}) { + const [shown, setShown] = useState(false); + const label = t(shown ? 'login.hide_password' : 'login.show_password'); + return html` +
+ + +
+ `; +} + // ── reCAPTCHA v2 helper ────────────────────────────────────────────────────── let _captchaSiteKey = null; @@ -183,9 +212,9 @@ export function LoginPage({ onLogin }) { setUsername(e.target.value)} autocomplete="username" required autofocus /> - setPassword(e.target.value)} - autocomplete="current-password" required /> + <${PasswordInput} placeholder=${t('login.password')} value=${password} + onInput=${e => setPassword(e.target.value)} + autocomplete="current-password" /> ${error && html`
${error}
`} ${pendingVerif && html`
@@ -474,9 +503,9 @@ export function RegisterPage() { setEmail(e.target.value)} autocomplete="email" required /> - setPassword(e.target.value)} - autocomplete="new-password" required minlength="8" /> + <${PasswordInput} placeholder=${t('register.password')} value=${password} + onInput=${e => setPassword(e.target.value)} + autocomplete="new-password" minlength="8" />
- setConfirm(e.target.value)} - autocomplete="new-password" required /> + <${PasswordInput} placeholder=${t('register.confirm')} value=${confirm} + onInput=${e => setConfirm(e.target.value)} + autocomplete="new-password" />