milestone 23 s3: convert auth/LoginPage.tsx to stylex

This commit is contained in:
2026-08-12 22:28:56 +02:00
parent 38d34453bb
commit 1de608f9bc
+59 -10
View File
@@ -1,8 +1,57 @@
import { useEffect, useState, type FormEvent } from "react"; import { useEffect, useState, type FormEvent } from "react";
import { useRouter, useSearch } from "@tanstack/react-router"; import { useRouter, useSearch } from "@tanstack/react-router";
import * as stylex from "@stylexjs/stylex";
import { ApiError } from "@/lib/api"; import { ApiError } from "@/lib/api";
import { useAuth } from "@/auth/store"; import { useAuth } from "@/auth/store";
import { inputClass, largePrimaryButtonClass } from "@/ui/classes"; import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
const styles = stylex.create({
/** Login renders outside AppShell, so it paints the page ground itself. */
page: {
display: "flex",
minHeight: "100dvh",
alignItems: "center",
justifyContent: "center",
backgroundColor: colors.surface,
color: colors.text,
padding: "1rem",
},
card: {
width: "100%",
maxWidth: "24rem",
},
heading: {
fontSize: "1.5rem",
lineHeight: "2rem",
fontWeight: 600,
},
probing: {
marginTop: "1rem",
color: colors.textMuted,
},
form: {
display: "flex",
flexDirection: "column",
gap: "1rem",
marginTop: "1.5rem",
},
fieldLabel: {
display: "block",
fontSize: "0.875rem",
lineHeight: "1.25rem",
fontWeight: 500,
},
submit: {
width: "100%",
},
error: {
marginTop: "1rem",
fontSize: "0.875rem",
lineHeight: "1.25rem",
color: colors.danger,
},
});
export function safeRedirect(raw: string | undefined): string { export function safeRedirect(raw: string | undefined): string {
if (raw === undefined) return "/"; if (raw === undefined) return "/";
@@ -76,15 +125,15 @@ export default function LoginPage() {
} }
return ( return (
<main className="flex min-h-dvh items-center justify-center bg-zinc-50 p-4 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100"> <main {...stylex.props(styles.page)}>
<section className="w-full max-w-sm"> <section {...stylex.props(styles.card)}>
<h1 className="text-2xl font-semibold">nxdns</h1> <h1 {...stylex.props(styles.heading)}>nxdns</h1>
{authRequired !== true ? ( {authRequired !== true ? (
<p className="mt-4 text-zinc-500">Checking whether a password is required</p> <p {...stylex.props(styles.probing)}>Checking whether a password is required</p>
) : ( ) : (
<form onSubmit={onSubmit} className="mt-6 space-y-4"> <form onSubmit={onSubmit} {...stylex.props(styles.form)}>
<div> <div>
<label htmlFor="password" className="block text-sm font-medium"> <label htmlFor="password" {...stylex.props(styles.fieldLabel)}>
Password Password
</label> </label>
<input <input
@@ -95,20 +144,20 @@ export default function LoginPage() {
required required
value={password} value={password}
onChange={(event) => setPassword(event.target.value)} onChange={(event) => setPassword(event.target.value)}
className={inputClass} {...stylex.props(shared.input, shared.focusRing)}
/> />
</div> </div>
<button <button
type="submit" type="submit"
disabled={busy || lockedOut} disabled={busy || lockedOut}
className={`w-full ${largePrimaryButtonClass}`} {...stylex.props(shared.largePrimaryButton, styles.submit, shared.focusRing)}
> >
{busy ? "Logging in…" : "Log in"} {busy ? "Logging in…" : "Log in"}
</button> </button>
</form> </form>
)} )}
{error !== null && ( {error !== null && (
<p role="alert" className="mt-4 text-sm text-red-600 dark:text-red-400"> <p role="alert" {...stylex.props(styles.error)}>
{errorMessage(error, remaining)} {errorMessage(error, remaining)}
</p> </p>
)} )}