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 { useRouter, useSearch } from "@tanstack/react-router";
import * as stylex from "@stylexjs/stylex";
import { ApiError } from "@/lib/api";
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 {
if (raw === undefined) return "/";
@@ -76,15 +125,15 @@ export default function LoginPage() {
}
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">
<section className="w-full max-w-sm">
<h1 className="text-2xl font-semibold">nxdns</h1>
<main {...stylex.props(styles.page)}>
<section {...stylex.props(styles.card)}>
<h1 {...stylex.props(styles.heading)}>nxdns</h1>
{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>
<label htmlFor="password" className="block text-sm font-medium">
<label htmlFor="password" {...stylex.props(styles.fieldLabel)}>
Password
</label>
<input
@@ -95,20 +144,20 @@ export default function LoginPage() {
required
value={password}
onChange={(event) => setPassword(event.target.value)}
className={inputClass}
{...stylex.props(shared.input, shared.focusRing)}
/>
</div>
<button
type="submit"
disabled={busy || lockedOut}
className={`w-full ${largePrimaryButtonClass}`}
{...stylex.props(shared.largePrimaryButton, styles.submit, shared.focusRing)}
>
{busy ? "Logging in…" : "Log in"}
</button>
</form>
)}
{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)}
</p>
)}