fix(auth): update auth page components
This commit is contained in:
parent
71f90bcd4d
commit
82475e95d5
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, type ReactNode } from "react";
|
import { useCallback, useEffect, useState, type ReactNode } from "react";
|
||||||
import { Apple, Eye, EyeOff, Globe, RotateCw, Send } from "lucide-react";
|
import { Apple, Eye, EyeOff, Globe, RotateCw, Send } from "lucide-react";
|
||||||
|
|
||||||
import { client, type CaptchaResponse } from "@/client";
|
import { client, type CaptchaResponse } from "@/client";
|
||||||
@ -8,10 +8,10 @@ import { Label } from "@/components/ui/label";
|
|||||||
|
|
||||||
export function Divider() {
|
export function Divider() {
|
||||||
return (
|
return (
|
||||||
<div className="my-5 flex items-center gap-4 text-xs font-medium uppercase text-zinc-400">
|
<div className="my-5 flex items-center gap-4 text-xs font-medium uppercase text-muted-foreground/60">
|
||||||
<div className="h-px flex-1 bg-zinc-200" />
|
<div className="h-px flex-1 bg-border" />
|
||||||
<span>or</span>
|
<span>or</span>
|
||||||
<div className="h-px flex-1 bg-zinc-200" />
|
<div className="h-px flex-1 bg-border" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -19,15 +19,15 @@ export function Divider() {
|
|||||||
export function SocialButtons() {
|
export function SocialButtons() {
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 grid grid-cols-3 gap-3">
|
<div className="mt-6 grid grid-cols-3 gap-3">
|
||||||
<Button className="h-11 rounded-lg border-zinc-200 bg-white text-zinc-950 hover:bg-zinc-50" type="button" variant="outline">
|
<Button className="h-11 rounded-xl border-border bg-background text-foreground hover:bg-muted" type="button" variant="outline">
|
||||||
<Apple className="size-5 fill-current" aria-hidden="true" />
|
<Apple className="size-5 fill-current" aria-hidden="true" />
|
||||||
<span className="sr-only">Continue with Apple</span>
|
<span className="sr-only">Continue with Apple</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="h-11 rounded-lg border-zinc-200 bg-white text-zinc-950 hover:bg-zinc-50" type="button" variant="outline">
|
<Button className="h-11 rounded-xl border-border bg-background text-foreground hover:bg-muted" type="button" variant="outline">
|
||||||
<Globe className="size-5 text-red-500" aria-hidden="true" />
|
<Globe className="size-5 text-destructive" aria-hidden="true" />
|
||||||
<span className="sr-only">Continue with Google</span>
|
<span className="sr-only">Continue with Google</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="h-11 rounded-lg border-zinc-200 bg-white text-sky-500 hover:bg-zinc-50" type="button" variant="outline">
|
<Button className="h-11 rounded-xl border-border bg-background text-primary hover:bg-muted" type="button" variant="outline">
|
||||||
<Send className="size-5 fill-current" aria-hidden="true" />
|
<Send className="size-5 fill-current" aria-hidden="true" />
|
||||||
<span className="sr-only">Continue with Twitter</span>
|
<span className="sr-only">Continue with Twitter</span>
|
||||||
</Button>
|
</Button>
|
||||||
@ -39,17 +39,20 @@ export function PasswordInput({
|
|||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
autoComplete = "current-password",
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
autoComplete?: string;
|
||||||
}) {
|
}) {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Input
|
<Input
|
||||||
className="h-11 rounded-lg border-zinc-200 pr-11 text-sm placeholder:text-zinc-400 focus-visible:ring-zinc-200"
|
className="h-11 rounded-xl border-input bg-background pr-11 text-sm placeholder:text-muted-foreground/50 focus-visible:ring-ring/20"
|
||||||
|
autoComplete={autoComplete}
|
||||||
id={id}
|
id={id}
|
||||||
name={name}
|
name={name}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
@ -58,7 +61,7 @@ export function PasswordInput({
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
aria-label={visible ? "Hide password" : "Show password"}
|
aria-label={visible ? "Hide password" : "Show password"}
|
||||||
className="absolute right-1.5 top-1/2 size-9 -translate-y-1/2 text-zinc-500 hover:bg-transparent"
|
className="absolute right-1.5 top-1/2 size-9 -translate-y-1/2 text-muted-foreground hover:bg-transparent"
|
||||||
onClick={() => setVisible((current) => !current)}
|
onClick={() => setVisible((current) => !current)}
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@ -77,7 +80,7 @@ export function CaptchaField({
|
|||||||
const [captcha, setCaptcha] = useState<CaptchaResponse | null>(null);
|
const [captcha, setCaptcha] = useState<CaptchaResponse | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const loadCaptcha = async () => {
|
const loadCaptcha = useCallback(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await client.authCaptcha({
|
const response = await client.authCaptcha({
|
||||||
@ -93,11 +96,12 @@ export function CaptchaField({
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
}, [onPublicKey]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void loadCaptcha();
|
const timer = window.setTimeout(() => void loadCaptcha(), 0);
|
||||||
}, []);
|
return () => window.clearTimeout(timer);
|
||||||
|
}, [loadCaptcha]);
|
||||||
|
|
||||||
const src = captcha?.base64?.startsWith("data:")
|
const src = captcha?.base64?.startsWith("data:")
|
||||||
? captcha.base64
|
? captcha.base64
|
||||||
@ -105,26 +109,28 @@ export function CaptchaField({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor="captcha">
|
<Label className="text-sm font-semibold text-foreground" htmlFor="captcha">
|
||||||
Captcha
|
Captcha
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<Input
|
<Input
|
||||||
className="h-11 rounded-lg border-zinc-200 text-sm placeholder:text-zinc-400 focus-visible:ring-zinc-200"
|
autoComplete="off"
|
||||||
|
className="h-11 rounded-xl border-input bg-background text-sm placeholder:text-muted-foreground/50 focus-visible:ring-ring/20"
|
||||||
id="captcha"
|
id="captcha"
|
||||||
|
inputMode="text"
|
||||||
name="captcha"
|
name="captcha"
|
||||||
placeholder="Enter captcha..."
|
placeholder="Enter captcha…"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
aria-label="Refresh captcha"
|
aria-label="Refresh captcha"
|
||||||
className="grid h-11 w-30 shrink-0 place-items-center rounded-lg border border-zinc-200 bg-zinc-50 text-zinc-500"
|
className="grid h-11 w-30 shrink-0 place-items-center rounded-xl border border-border bg-muted/40 text-muted-foreground"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onClick={() => void loadCaptcha()}
|
onClick={() => void loadCaptcha()}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{captcha ? (
|
{captcha ? (
|
||||||
<img alt="Captcha" className="h-9 max-w-28 object-contain" src={src} />
|
<img alt="Captcha" className="h-9 max-w-28 object-contain" height={36} src={src} width={112} />
|
||||||
) : (
|
) : (
|
||||||
<RotateCw className="size-4" />
|
<RotateCw className="size-4" />
|
||||||
)}
|
)}
|
||||||
@ -149,15 +155,17 @@ export function TextField({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor={id}>
|
<Label className="text-sm font-semibold text-foreground" htmlFor={id}>
|
||||||
{label}
|
{label}
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
className="h-11 rounded-lg border-zinc-200 text-sm placeholder:text-zinc-400 focus-visible:ring-zinc-200"
|
autoComplete={type === "email" ? "email" : name === "username" ? "username" : "off"}
|
||||||
|
className="h-11 rounded-xl border-input bg-background text-sm placeholder:text-muted-foreground/50 focus-visible:ring-ring/20"
|
||||||
id={id}
|
id={id}
|
||||||
name={name}
|
name={name}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
required
|
required
|
||||||
|
spellCheck={type === "email" || name === "username" ? false : undefined}
|
||||||
type={type}
|
type={type}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -167,10 +175,11 @@ export function TextField({
|
|||||||
export function FormMessage({ children, tone }: { children: ReactNode; tone: "error" | "success" }) {
|
export function FormMessage({ children, tone }: { children: ReactNode; tone: "error" | "success" }) {
|
||||||
return (
|
return (
|
||||||
<p
|
<p
|
||||||
|
aria-live="polite"
|
||||||
className={
|
className={
|
||||||
tone === "error"
|
tone === "error"
|
||||||
? "rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600"
|
? "rounded-xl bg-destructive/10 px-3 py-2 text-sm text-destructive"
|
||||||
: "rounded-lg bg-emerald-50 px-3 py-2 text-sm text-emerald-700"
|
: "rounded-xl bg-primary/10 px-3 py-2 text-sm text-primary"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export default function ForgotPasswordPage() {
|
|||||||
id="email"
|
id="email"
|
||||||
label="E-Mail Address"
|
label="E-Mail Address"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="Enter your email..."
|
placeholder="Enter your email…"
|
||||||
type="email"
|
type="email"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -49,16 +49,16 @@ export default function ForgotPasswordPage() {
|
|||||||
{success && <FormMessage tone="success">{success}</FormMessage>}
|
{success && <FormMessage tone="success">{success}</FormMessage>}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="h-11 w-full rounded-lg bg-zinc-950 text-base text-white shadow-inner shadow-white/10 hover:bg-zinc-800"
|
className="h-11 w-full rounded-xl text-base shadow-inner shadow-primary-foreground/10"
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{submitting ? "Please wait..." : "Send reset link"}
|
{submitting ? "Please wait…" : "Send reset link"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<footer className="mt-6 text-center text-base text-zinc-500">
|
<footer className="mt-6 text-center text-base text-muted-foreground">
|
||||||
<Link className="font-semibold text-zinc-950" to="/auth/login">
|
<Link className="font-semibold text-foreground transition-colors hover:text-primary" to="/auth/login">
|
||||||
Back to sign in
|
Back to sign in
|
||||||
</Link>
|
</Link>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { useAuth } from "@/context/auth-context";
|
|||||||
|
|
||||||
function AuthLogo() {
|
function AuthLogo() {
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid size-12 place-items-center rounded-lg bg-gradient-to-b from-[oklch(0.45_0.24_290)] to-[oklch(0.55_0.24_290)] shadow-[0_14px_30px_rgba(134,59,255,0.24)]">
|
<div className="mx-auto grid size-12 place-items-center rounded-2xl bg-primary text-primary-foreground shadow-lg shadow-primary/20">
|
||||||
<div className="relative size-8 overflow-hidden rounded-sm bg-white/20">
|
<div className="relative size-8 overflow-hidden rounded-lg bg-primary-foreground/20">
|
||||||
<span className="absolute left-1.5 top-2 h-1 w-6 rounded-full bg-white" />
|
<span className="absolute left-1.5 top-2 h-1 w-6 rounded-full bg-white" />
|
||||||
<span className="absolute left-1 top-3.5 h-1 w-7 rounded-full bg-white/90" />
|
<span className="absolute left-1 top-3.5 h-1 w-7 rounded-full bg-white/90" />
|
||||||
<span className="absolute left-2 top-5 h-1 w-6 rounded-full bg-white/80" />
|
<span className="absolute left-2 top-5 h-1 w-6 rounded-full bg-white/80" />
|
||||||
@ -17,10 +17,10 @@ function AuthLogo() {
|
|||||||
|
|
||||||
export function AuthPanel({ children }: { children: ReactNode }) {
|
export function AuthPanel({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<section className="relative z-10 w-full max-w-[460px] rounded-lg bg-card px-6 py-8 shadow-[0_24px_64px_rgba(134,59,255,0.08)] sm:px-9">
|
<section className="relative z-10 w-full max-w-[460px] rounded-2xl border border-border/50 bg-card px-6 py-8 shadow-xl shadow-primary/[0.04] sm:px-9">
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 overflow-hidden rounded-t-lg">
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 overflow-hidden rounded-t-2xl">
|
||||||
<div className="absolute inset-0 bg-[linear-gradient(rgba(134,59,255,0.10)_1px,transparent_1px),linear-gradient(90deg,rgba(134,59,255,0.10)_1px,transparent_1px)] bg-[size:38px_38px] [mask-image:linear-gradient(to_bottom,black,transparent)]" />
|
<div className="absolute inset-0 bg-[linear-gradient(var(--border)_1px,transparent_1px),linear-gradient(90deg,var(--border)_1px,transparent_1px)] bg-[size:38px_38px] opacity-40 [mask-image:linear-gradient(to_bottom,black,transparent)]" />
|
||||||
<div className="absolute inset-x-10 top-0 h-24 bg-gradient-to-b from-[oklch(0.40_0.12_290)/0.15] to-transparent blur-2xl" />
|
<div className="absolute inset-x-10 top-0 h-24 bg-primary/10 blur-2xl" />
|
||||||
</div>
|
</div>
|
||||||
{children}
|
{children}
|
||||||
</section>
|
</section>
|
||||||
@ -55,11 +55,11 @@ export default function AuthLayout() {
|
|||||||
return (
|
return (
|
||||||
<main className="min-h-svh bg-background px-4 py-6 text-foreground">
|
<main className="min-h-svh bg-background px-4 py-6 text-foreground">
|
||||||
<div className="relative mx-auto grid min-h-[calc(100svh-3rem)] w-full max-w-5xl place-items-center overflow-hidden">
|
<div className="relative mx-auto grid min-h-[calc(100svh-3rem)] w-full max-w-5xl place-items-center overflow-hidden">
|
||||||
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(rgba(134,59,255,0.05)_1px,transparent_1px),linear-gradient(90deg,rgba(134,59,255,0.05)_1px,transparent_1px)] bg-[size:72px_72px] [mask-image:radial-gradient(circle_at_center,black,transparent_70%)]" />
|
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(var(--border)_1px,transparent_1px),linear-gradient(90deg,var(--border)_1px,transparent_1px)] bg-[size:72px_72px] opacity-35 [mask-image:radial-gradient(circle_at_center,black,transparent_70%)]" />
|
||||||
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(134,59,255,0.15),transparent_50%)]" />
|
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_center,var(--primary),transparent_55%)] opacity-10" />
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="relative z-10 text-sm font-mono font-medium text-muted-foreground">
|
<div className="relative z-10 text-sm font-mono font-medium text-muted-foreground">
|
||||||
Loading...
|
Loading…
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|||||||
@ -124,24 +124,24 @@ export default function LoginPage() {
|
|||||||
id="username"
|
id="username"
|
||||||
label="Username or E-Mail Address"
|
label="Username or E-Mail Address"
|
||||||
name="username"
|
name="username"
|
||||||
placeholder="Enter your username or email..."
|
placeholder="Enter your username or email…"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor="password">
|
<Label className="text-sm font-semibold text-foreground" htmlFor="password">
|
||||||
Password
|
Password
|
||||||
</Label>
|
</Label>
|
||||||
<PasswordInput id="password" name="password" placeholder="Enter your password..." />
|
<PasswordInput id="password" name="password" placeholder="Enter your password…" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CaptchaField onPublicKey={setPublicKey} />
|
<CaptchaField onPublicKey={setPublicKey} />
|
||||||
|
|
||||||
<div className="flex items-center justify-between gap-4 text-sm">
|
<div className="flex items-center justify-between gap-4 text-sm">
|
||||||
<label className="flex items-center gap-3 font-medium text-zinc-950">
|
<label className="flex items-center gap-3 font-medium text-foreground">
|
||||||
<Checkbox className="size-4 rounded-[5px] border-zinc-200" name="remember" />
|
<Checkbox className="size-4 rounded-md border-border" name="remember" />
|
||||||
Remember me
|
Remember me
|
||||||
</label>
|
</label>
|
||||||
<Link className="font-medium text-zinc-600 underline underline-offset-4" to="/auth/forgot-password">
|
<Link className="font-medium text-muted-foreground underline underline-offset-4 transition-colors hover:text-foreground" to="/auth/forgot-password">
|
||||||
Forgot password?
|
Forgot password?
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -149,17 +149,17 @@ export default function LoginPage() {
|
|||||||
{error && <FormMessage tone="error">{error}</FormMessage>}
|
{error && <FormMessage tone="error">{error}</FormMessage>}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="h-11 w-full rounded-lg bg-zinc-950 text-base text-white shadow-inner shadow-white/10 hover:bg-zinc-800"
|
className="h-11 w-full rounded-xl text-base shadow-inner shadow-primary-foreground/10"
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{submitting ? "Please wait..." : "Sign in"}
|
{submitting ? "Please wait…" : "Sign in"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<footer className="mt-6 text-center text-base text-zinc-500">
|
<footer className="mt-6 text-center text-base text-muted-foreground">
|
||||||
Don't have an account yet?{" "}
|
Don't have an account yet?{" "}
|
||||||
<Link className="font-semibold text-zinc-950" to="/auth/register">
|
<Link className="font-semibold text-foreground transition-colors hover:text-primary" to="/auth/register">
|
||||||
Sign Up
|
Sign Up
|
||||||
</Link>
|
</Link>
|
||||||
</footer>
|
</footer>
|
||||||
@ -196,11 +196,11 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
<DialogFooter className="-mx-4 -mb-4">
|
<DialogFooter className="-mx-4 -mb-4">
|
||||||
<Button
|
<Button
|
||||||
className="h-10 bg-zinc-950 text-white hover:bg-zinc-800"
|
className="h-10"
|
||||||
disabled={twoFactorSubmitting}
|
disabled={twoFactorSubmitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{twoFactorSubmitting ? "Verifying..." : "Verify"}
|
{twoFactorSubmitting ? "Verifying…" : "Verify"}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -58,26 +58,26 @@ export default function RegisterPage() {
|
|||||||
<AuthHeader description="Please enter your details to sign up." title="Create account" />
|
<AuthHeader description="Please enter your details to sign up." title="Create account" />
|
||||||
|
|
||||||
<form className="relative space-y-4 mt-10" onSubmit={(event) => void handleSubmit(event)}>
|
<form className="relative space-y-4 mt-10" onSubmit={(event) => void handleSubmit(event)}>
|
||||||
<TextField id="username" label="Username" name="username" placeholder="Enter your username..." />
|
<TextField id="username" label="Username" name="username" placeholder="Enter your username…" />
|
||||||
<TextField
|
<TextField
|
||||||
id="email"
|
id="email"
|
||||||
label="E-Mail Address"
|
label="E-Mail Address"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="Enter your email..."
|
placeholder="Enter your email…"
|
||||||
type="email"
|
type="email"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor="password">
|
<Label className="text-sm font-semibold text-foreground" htmlFor="password">
|
||||||
Password
|
Password
|
||||||
</Label>
|
</Label>
|
||||||
<PasswordInput id="password" name="password" placeholder="Enter your password..." />
|
<PasswordInput autoComplete="new-password" id="password" name="password" placeholder="Enter your password…" />
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor="confirmPassword">
|
<Label className="text-sm font-semibold text-foreground" htmlFor="confirmPassword">
|
||||||
Confirm Password
|
Confirm Password
|
||||||
</Label>
|
</Label>
|
||||||
<PasswordInput id="confirmPassword" name="confirmPassword" placeholder="Enter your password again..." />
|
<PasswordInput autoComplete="new-password" id="confirmPassword" name="confirmPassword" placeholder="Enter your password again…" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CaptchaField onPublicKey={setPublicKey} />
|
<CaptchaField onPublicKey={setPublicKey} />
|
||||||
@ -85,17 +85,17 @@ export default function RegisterPage() {
|
|||||||
{error && <FormMessage tone="error">{error}</FormMessage>}
|
{error && <FormMessage tone="error">{error}</FormMessage>}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="h-11 w-full rounded-lg bg-zinc-950 text-base text-white shadow-inner shadow-white/10 hover:bg-zinc-800"
|
className="h-11 w-full rounded-xl text-base shadow-inner shadow-primary-foreground/10"
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{submitting ? "Please wait..." : "Sign up"}
|
{submitting ? "Please wait…" : "Sign up"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<footer className="mt-6 text-center text-base text-zinc-500">
|
<footer className="mt-6 text-center text-base text-muted-foreground">
|
||||||
Already have an account?{" "}
|
Already have an account?{" "}
|
||||||
<Link className="font-semibold text-zinc-950" to="/auth/login">
|
<Link className="font-semibold text-foreground transition-colors hover:text-primary" to="/auth/login">
|
||||||
Sign In
|
Sign In
|
||||||
</Link>
|
</Link>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@ -40,29 +40,29 @@ export default function ResetPasswordPage() {
|
|||||||
|
|
||||||
<form className="relative mt-6 space-y-4" onSubmit={(event) => void handleSubmit(event)}>
|
<form className="relative mt-6 space-y-4" onSubmit={(event) => void handleSubmit(event)}>
|
||||||
{!searchParams.get("token") && (
|
{!searchParams.get("token") && (
|
||||||
<TextField id="token" label="Reset Token" name="token" placeholder="Enter your reset token..." />
|
<TextField id="token" label="Reset Token" name="token" placeholder="Enter your reset token…" />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-sm font-semibold text-zinc-950" htmlFor="password">
|
<Label className="text-sm font-semibold text-foreground" htmlFor="password">
|
||||||
Password
|
Password
|
||||||
</Label>
|
</Label>
|
||||||
<PasswordInput id="password" name="password" placeholder="Enter your password..." />
|
<PasswordInput autoComplete="new-password" id="password" name="password" placeholder="Enter your password…" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error && <FormMessage tone="error">{error}</FormMessage>}
|
{error && <FormMessage tone="error">{error}</FormMessage>}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="h-11 w-full rounded-lg bg-zinc-950 text-base text-white shadow-inner shadow-white/10 hover:bg-zinc-800"
|
className="h-11 w-full rounded-xl text-base shadow-inner shadow-primary-foreground/10"
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{submitting ? "Please wait..." : "Reset password"}
|
{submitting ? "Please wait…" : "Reset password"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<footer className="mt-6 text-center text-base text-zinc-500">
|
<footer className="mt-6 text-center text-base text-muted-foreground">
|
||||||
<Link className="font-semibold text-zinc-950" to="/auth/login">
|
<Link className="font-semibold text-foreground transition-colors hover:text-primary" to="/auth/login">
|
||||||
Back to sign in
|
Back to sign in
|
||||||
</Link>
|
</Link>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user