auto-save 2026-05-15 16:10 (+1, ~4)

This commit is contained in:
2026-05-15 16:11:10 +08:00
parent ac36c4e35d
commit 5ca9846748
5 changed files with 130 additions and 79 deletions

View File

@@ -1,6 +1,6 @@
"use client"
import type { CSSProperties, FormEvent } from "react"
import type { FormEvent } from "react"
import { useEffect, useMemo, useState } from "react"
import {
AlertCircle,
@@ -13,9 +13,9 @@ import {
Sparkles,
UserRound,
} from "lucide-react"
import { AnimatedLoginCharacters, type LoginCharacterMood } from "@/components/login/animated-login-characters"
type LoginStatus = "idle" | "loading" | "success"
type LoginMood = "idle" | "typing" | "peek" | "error" | "success"
export default function LoginPage() {
const [username, setUsername] = useState("")
@@ -39,7 +39,7 @@ export default function LoginPage() {
return () => window.removeEventListener("pointermove", onPointerMove)
}, [])
const mood: LoginMood = useMemo(() => {
const mood: LoginCharacterMood = useMemo(() => {
if (status === "success") return "success"
if (error) return "error"
if (showPassword && activeField === "password") return "peek"
@@ -87,13 +87,6 @@ export default function LoginPage() {
return (
<main
className="login-page relative min-h-screen overflow-hidden px-5 py-6 text-white sm:px-8 lg:px-10"
data-mood={mood}
style={
{
"--eye-x": `${eyeOffset.x}px`,
"--eye-y": `${eyeOffset.y}px`,
} as CSSProperties
}
>
<div className="relative z-10 mx-auto flex min-h-[calc(100vh-3rem)] w-full max-w-7xl items-center">
<div className="grid w-full gap-5 lg:grid-cols-[minmax(0,1.08fr)_minmax(380px,460px)] lg:items-stretch">
@@ -115,42 +108,7 @@ export default function LoginPage() {
</div>
</div>
<div className="login-character-stage" aria-hidden="true">
<div className="login-stage-grid" />
<div className="login-characters-container">
<div className="login-figure login-figure--purple">
<span className="login-eyes login-eyes--purple">
<span className="login-eye" />
<span className="login-eye" />
</span>
<span className="login-mouth login-mouth--purple" />
</div>
<div className="login-figure login-figure--black">
<span className="login-eyes login-eyes--black">
<span className="login-eye login-eye--small" />
<span className="login-eye login-eye--small" />
</span>
</div>
<div className="login-figure login-figure--orange">
<span className="login-eyes login-eyes--orange">
<span className="login-pupil" />
<span className="login-pupil" />
</span>
<span className="login-mouth login-mouth--orange" />
</div>
<div className="login-figure login-figure--yellow">
<span className="login-eyes login-eyes--yellow">
<span className="login-pupil" />
<span className="login-pupil" />
</span>
<span className="login-yellow-mouth">
<svg width="80" height="20" viewBox="0 0 80 20">
<path d="M0 10 Q10 10, 20 10 Q30 10, 40 10 Q50 10, 60 10 Q70 10, 80 10" />
</svg>
</span>
</div>
</div>
</div>
<AnimatedLoginCharacters mood={mood} eyeOffset={eyeOffset} />
<div className="grid gap-3 sm:grid-cols-3">
{[