From 23398c4ac0f598281a82e2a3a1ddb1fdd6522dc1 Mon Sep 17 00:00:00 2001 From: parththakkar106 Date: Thu, 6 Aug 2026 20:47:04 +0530 Subject: [PATCH] Fix the mismatched email field and rework the auth modal The global input styling in index.css enumerates types, and `email` was never in the list, so the Email box fell through to browser defaults while the Password box right below it got the app treatment. Added it to both copies of that selector list -- the base rule and the 16px iOS-zoom rule in the mobile block; missing the second would revert the fix on phones. While in there, the modal itself: log in / sign up are now segmented tabs instead of a link crammed into the button row, fields carry autoComplete so password managers work at all, a show/hide toggle on the password, Esc to dismiss, and the error is a real role=alert box rather than the shared .test-error text. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UeQVy5bEjLhfgWNc27Efet --- frontend/src/components.jsx | 74 +++++++++++++++++++++++++++---------- frontend/src/index.css | 74 ++++++++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 21 deletions(-) diff --git a/frontend/src/components.jsx b/frontend/src/components.jsx index a16f378..7dd53aa 100644 --- a/frontend/src/components.jsx +++ b/frontend/src/components.jsx @@ -238,18 +238,34 @@ export function AuthModal({ mode: initialMode, onClose, onAuthed }) { const [mode, setMode] = useState(initialMode || 'register') const [email, setEmail] = useState('') const [password, setPassword] = useState('') + const [reveal, setReveal] = useState(false) const [error, setError] = useState('') const [busy, setBusy] = useState(false) const registering = mode === 'register' + // Esc dismisses, like the overlay click already does. + useEffect(() => { + const onKey = (e) => { if (e.key === 'Escape') onClose() } + window.addEventListener('keydown', onKey) + return () => window.removeEventListener('keydown', onKey) + }, [onClose]) + + const switchTo = (next) => { + if (next === mode) return + setMode(next) + setError('') + setReveal(false) + } + const submit = async (e) => { e.preventDefault() setBusy(true) setError('') try { + const address = email.trim() const me = registering - ? await api.register(email, password) - : await api.login(email, password) + ? await api.register(address, password) + : await api.login(address, password) onAuthed(me, mode) } catch (err) { setError(err.message) @@ -259,34 +275,54 @@ export function AuthModal({ mode: initialMode, onClose, onAuthed }) { return (
-
e.stopPropagation()} onSubmit={submit}> -

{registering ? 'Create an account' : 'Log in'}

-

+ e.stopPropagation()} onSubmit={submit} + aria-labelledby="auth-title"> +

+

{registering ? 'Create an account' : 'Welcome back'}

+

{registering ? 'Everything you’ve played as a guest stays with your new account, and you can pick it up from any device.' - : 'Welcome back — log in to reach your adventures.'} + : 'Log in to reach your adventures.'}

+ +
+ + +
+ - {error &&
{error}
} -
- -
- -
+ {registering && At least 8 characters.} + + + {error &&
{error}
} + +
+ +
diff --git a/frontend/src/index.css b/frontend/src/index.css index edb642b..0b82463 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -184,7 +184,7 @@ label.field .label { color: var(--text-dim); margin-bottom: 5px; } -input[type="text"], input[type="password"], input[type="number"], textarea, select { +input[type="text"], input[type="email"], input[type="password"], input[type="number"], textarea, select { width: 100%; background: var(--bg-input); color: var(--text); @@ -1262,6 +1262,76 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n .modal .modal-hint { margin: 0 0 18px; color: var(--text-dim); font-size: 0.88rem; } .modal .modal-buttons { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; } +/* ---------- Auth (log in / sign up) ---------- */ + +.auth-modal { width: min(400px, calc(100vw - 40px)); text-align: center; padding-top: 22px; } +.auth-crest { + font-size: 1.1rem; + color: var(--accent-dim); + letter-spacing: 0.3em; + margin-bottom: 6px; +} +.auth-modal h2 { font-size: 1.35rem; } +.auth-modal .auth-hint { margin-bottom: 16px; line-height: 1.45; } +/* Fields go back to left-aligned — only the header is centred. */ +.auth-modal label.field { text-align: left; } + +.auth-tabs { + display: flex; + gap: 4px; + padding: 4px; + margin-bottom: 18px; + background: var(--bg-input); + border: 1px solid var(--border); + border-radius: 10px; +} +.auth-tab { + flex: 1; + padding: 7px 0; + border: 1px solid transparent; + border-radius: 7px; + background: transparent; + color: var(--text-dim); + font-family: var(--font-display); + font-size: 0.78rem; + letter-spacing: 0.1em; + text-transform: uppercase; +} +.auth-tab:hover { color: var(--text); background: rgba(212, 169, 78, 0.06); } +.auth-tab.active { + background: var(--bg-panel); + border-color: var(--accent-dim); + color: var(--accent-bright); +} + +.auth-password { display: flex; gap: 8px; } +.auth-password input { flex: 1; min-width: 0; } +.auth-reveal { + flex: none; + padding: 0 12px; + font-size: 0.78rem; + color: var(--text-dim); +} +.auth-reveal:hover { color: var(--accent-bright); } + +.auth-help { + display: block; + margin-top: 6px; + font-size: 0.76rem; + color: var(--text-dim); +} +.auth-error { + margin-top: 4px; + padding: 9px 12px; + border: 1px solid rgba(208, 101, 101, 0.45); + border-radius: 8px; + background: rgba(208, 101, 101, 0.09); + color: var(--danger); + font-size: 0.85rem; + text-align: left; + white-space: pre-wrap; +} + /* "Update from scenario" — a wider modal, since it lists a diff. */ .refresh-modal { width: min(620px, calc(100vw - 40px)); } .refresh-changes { @@ -1984,7 +2054,7 @@ button.primary.compact { padding: 3px 12px; font-size: 0.76rem; margin-left: aut /* ---------- Global page padding / typography ---------- */ .page { padding: 18px 14px; } /* 16px inputs stop iOS Safari auto-zooming when a field is focused. */ - input[type="text"], input[type="password"], input[type="number"], textarea, select { + input[type="text"], input[type="email"], input[type="password"], input[type="number"], textarea, select { font-size: 16px; }