milestone 23 s3: convert auth/LoginPage.tsx to stylex
This commit is contained in:
+59
-10
@@ -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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user