feat(auth): redesign auth UI to match Dart original
- Full-bleed bg_login.png background outside 500px MobileShell - Facebook landing: logo + Facebook pill button + "Other Sign In Options" link - Replace centered Dialog with true bottom sheet (drag handle, top radius 28px) - Email panel: internal login/register toggle, no separate route - Pink gradient primary button (#f96ADE → #f657A0) - Pill input fields (46px, white, radius 24, pink 10% shadow) - Pink circular checkbox + bold Privacy/Terms rich text (visual only, non-blocking) - Floating 40x40 white back button (top:20/left:20) - Wire AuthPanelModeChanged dispatch for panel switching - New design tokens (--color-auth-*, --auth-*, --radius-bottom-sheet) - New generic BottomSheet component - Copy ic-logo-login.png (+@2x, +@3x) from Dart assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,13 @@
|
||||
* 邮箱注册表单
|
||||
*
|
||||
* 原始 Dart: lib/ui/auth/widgets/email_register_form.dart
|
||||
*
|
||||
* 视觉规格(与 Dart 对齐):
|
||||
* - 4 字段:username / email / password / confirmPassword(顺序与 Dart 一致)
|
||||
* - 字段无 label(仅 placeholder)
|
||||
* - 错误仅以红色横幅显示(AuthErrorMessage),无字段级错误
|
||||
* - 切换链接由父级 AuthEmailPanel 渲染
|
||||
* - 提交派发 `AuthEmailRegisterSubmitted`
|
||||
*/
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -20,13 +27,11 @@ import { AuthErrorMessage } from "./auth-error-message";
|
||||
import styles from "./email-form.module.css";
|
||||
|
||||
export interface EmailRegisterFormProps {
|
||||
onSwitchToLogin: () => void;
|
||||
globalError?: string | null;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export function EmailRegisterForm({
|
||||
onSwitchToLogin,
|
||||
globalError,
|
||||
isLoading,
|
||||
}: EmailRegisterFormProps) {
|
||||
@@ -35,25 +40,13 @@ export function EmailRegisterForm({
|
||||
const [password, setPassword] = useState("");
|
||||
const [username, setUsername] = useState("");
|
||||
const [confirmPassword, setConfirmPassword] = useState("");
|
||||
const [errors, setErrors] = useState<
|
||||
Partial<Record<"email" | "password" | "username" | "confirmPassword", string>>
|
||||
>({});
|
||||
|
||||
const submit = () => {
|
||||
const emailErr = validateEmail(email);
|
||||
const passwordErr = validatePassword(password);
|
||||
const usernameErr = validateUsername(username);
|
||||
const confirmErr = validateConfirmPassword(password, confirmPassword);
|
||||
if (emailErr || passwordErr || usernameErr || confirmErr) {
|
||||
setErrors({
|
||||
email: emailErr ?? undefined,
|
||||
password: passwordErr ?? undefined,
|
||||
username: usernameErr ?? undefined,
|
||||
confirmPassword: confirmErr ?? undefined,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setErrors({});
|
||||
if (emailErr || passwordErr || usernameErr || confirmErr) return;
|
||||
dispatch({
|
||||
type: "AuthEmailRegisterSubmitted",
|
||||
email,
|
||||
@@ -71,53 +64,38 @@ export function EmailRegisterForm({
|
||||
submit();
|
||||
}}
|
||||
>
|
||||
<AuthErrorMessage message={globalError ?? null} />
|
||||
<AuthTextField
|
||||
label="Username"
|
||||
value={username}
|
||||
onChange={setUsername}
|
||||
placeholder="cozsweet_user"
|
||||
placeholder="Username"
|
||||
autoComplete="username"
|
||||
errorMessage={errors.username ?? null}
|
||||
/>
|
||||
<AuthTextField
|
||||
label="Email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={setEmail}
|
||||
placeholder="you@example.com"
|
||||
placeholder="Email"
|
||||
autoComplete="email"
|
||||
errorMessage={errors.email ?? null}
|
||||
/>
|
||||
<AuthTextField
|
||||
label="Password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={setPassword}
|
||||
placeholder="••••••••"
|
||||
placeholder="Password"
|
||||
autoComplete="new-password"
|
||||
errorMessage={errors.password ?? null}
|
||||
/>
|
||||
<AuthTextField
|
||||
label="Confirm Password"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={setConfirmPassword}
|
||||
placeholder="••••••••"
|
||||
placeholder="Confirm Password"
|
||||
autoComplete="new-password"
|
||||
errorMessage={errors.confirmPassword ?? null}
|
||||
onSubmit={submit}
|
||||
/>
|
||||
<AuthErrorMessage message={globalError ?? null} />
|
||||
<AuthPrimaryButton type="submit" isLoading={isLoading}>
|
||||
Create Account
|
||||
Register
|
||||
</AuthPrimaryButton>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.linkButton}
|
||||
onClick={onSwitchToLogin}
|
||||
>
|
||||
Already have an account? <span className={styles.link}>Log in</span>
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user