diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index 4d1d494a3..adaefb661 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useId, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { KeyRound, Lock, Loader2 } from "lucide-react"; @@ -23,6 +23,12 @@ export default function LoginPage() { const [password, setPassword] = useState(""); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); + // v1.4.27 MB3 — explicit error-region id so the email + password + // inputs reference the banner via `aria-describedby`. Screen readers + // pair the error with the field instead of announcing it as a + // standalone alert detached from the form. + const errorId = useId(); + const errorDescriptor = error ? errorId : undefined; const { data: registrationEnabled } = useQuery({ queryKey: ["auth", "registration-status"], queryFn: async () => { @@ -176,6 +182,13 @@ export default function LoginPage() { onChange={(e) => setEmail(e.target.value)} required autoComplete="username" + inputMode="email" + enterKeyHint="next" + autoCapitalize="none" + spellCheck={false} + aria-required="true" + aria-invalid={!!error || undefined} + aria-describedby={errorDescriptor} placeholder={t("auth.emailOrUsernamePlaceholder")} /> @@ -188,6 +201,10 @@ export default function LoginPage() { onChange={(e) => setPassword(e.target.value)} required autoComplete="current-password" + enterKeyHint="go" + aria-required="true" + aria-invalid={!!error || undefined} + aria-describedby={errorDescriptor} placeholder="********" /> @@ -216,7 +233,9 @@ export default function LoginPage() { {error && ( @@ -98,6 +110,12 @@ export default function RegisterPage() { placeholder="user" required autoComplete="username" + enterKeyHint="next" + autoCapitalize="none" + spellCheck={false} + aria-required="true" + aria-invalid={!!error || undefined} + aria-describedby={errorDescriptor} minLength={3} maxLength={30} /> @@ -113,6 +131,10 @@ export default function RegisterPage() { placeholder={t("auth.passwordMinLength")} required autoComplete="new-password" + enterKeyHint="go" + aria-required="true" + aria-invalid={!!error || undefined} + aria-describedby={errorDescriptor} />

@@ -122,7 +144,9 @@ export default function RegisterPage() { {error && (