refactor(auth): migrate shell styles to tailwind
This commit is contained in:
@@ -13,7 +13,6 @@ import { ROUTES } from "@/router/routes";
|
|||||||
import { useAppNavigator } from "@/router/use-app-navigator";
|
import { useAppNavigator } from "@/router/use-app-navigator";
|
||||||
|
|
||||||
import { AuthBackground, AuthPanel } from "./components";
|
import { AuthBackground, AuthPanel } from "./components";
|
||||||
import styles from "./components/auth-screen.module.css";
|
|
||||||
import { Logger } from "@/utils";
|
import { Logger } from "@/utils";
|
||||||
|
|
||||||
const log = new Logger("AppAuthAuthScreen");
|
const log = new Logger("AppAuthAuthScreen");
|
||||||
@@ -51,9 +50,15 @@ export function AuthScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MobileShell>
|
<MobileShell>
|
||||||
<div className={styles.wrapper}>
|
<div className="relative flex min-h-[var(--app-viewport-height,100dvh)] w-full flex-1 flex-col overflow-hidden bg-[#fbf1f2]">
|
||||||
<AuthBackground />
|
<AuthBackground />
|
||||||
<div className={styles.content}>
|
<div
|
||||||
|
className="relative z-[2] flex flex-auto flex-col justify-center"
|
||||||
|
style={{
|
||||||
|
padding:
|
||||||
|
"calc(var(--page-padding-y, var(--spacing-lg)) + var(--app-safe-top, 0px)) calc(var(--page-padding-x, var(--spacing-lg)) + var(--app-safe-right, 0px)) calc(var(--page-padding-y, var(--spacing-lg)) + var(--app-safe-bottom, 0px)) calc(var(--page-padding-x, var(--spacing-lg)) + var(--app-safe-left, 0px))",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<AuthPanel />
|
<AuthPanel />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
import { renderToStaticMarkup } from "react-dom/server";
|
import { renderToStaticMarkup } from "react-dom/server";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { AuthBackground } from "../auth-background";
|
||||||
import { AuthErrorMessage } from "../auth-error-message";
|
import { AuthErrorMessage } from "../auth-error-message";
|
||||||
|
import { EmailLoginForm } from "../email-login-form";
|
||||||
|
import { EmailRegisterForm } from "../email-register-form";
|
||||||
|
|
||||||
|
vi.mock("@/stores/auth/auth-context", () => ({
|
||||||
|
useAuthDispatch: () => vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe("auth Tailwind components", () => {
|
describe("auth Tailwind components", () => {
|
||||||
it("renders AuthErrorMessage only when a message is present", () => {
|
it("renders AuthErrorMessage only when a message is present", () => {
|
||||||
@@ -12,4 +19,34 @@ describe("auth Tailwind components", () => {
|
|||||||
expect(html).toContain("text-error");
|
expect(html).toContain("text-error");
|
||||||
expect(html).toContain("Invalid email");
|
expect(html).toContain("Invalid email");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders EmailLoginForm with Tailwind form layout", () => {
|
||||||
|
const html = renderToStaticMarkup(<EmailLoginForm />);
|
||||||
|
|
||||||
|
expect(html).toContain("<form");
|
||||||
|
expect(html).toContain("flex");
|
||||||
|
expect(html).toContain("w-full");
|
||||||
|
expect(html).toContain("gap-md");
|
||||||
|
expect(html).toContain("Login");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders EmailRegisterForm with Tailwind form layout", () => {
|
||||||
|
const html = renderToStaticMarkup(<EmailRegisterForm />);
|
||||||
|
|
||||||
|
expect(html).toContain("<form");
|
||||||
|
expect(html).toContain("flex");
|
||||||
|
expect(html).toContain("w-full");
|
||||||
|
expect(html).toContain("gap-md");
|
||||||
|
expect(html).toContain("Register");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders AuthBackground with Tailwind layout classes", () => {
|
||||||
|
const html = renderToStaticMarkup(<AuthBackground />);
|
||||||
|
|
||||||
|
expect(html).toContain("absolute");
|
||||||
|
expect(html).toContain("inset-0");
|
||||||
|
expect(html).toContain("bg-[#fbf1f2]");
|
||||||
|
expect(html).toContain("object-cover");
|
||||||
|
expect(html).toContain("%2Fimages%2Fauth%2Fbg-login.png");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/* Auth 背景图片容器(与 splash-background.module.css 同款) */
|
|
||||||
|
|
||||||
.bg {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
z-index: 0;
|
|
||||||
background: #fbf1f2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image {
|
|
||||||
object-fit: cover;
|
|
||||||
object-position: center;
|
|
||||||
}
|
|
||||||
@@ -5,18 +5,17 @@
|
|||||||
* 资源: /public/images/auth/bg-login.png
|
* 资源: /public/images/auth/bg-login.png
|
||||||
*/
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import styles from "./auth-background.module.css";
|
|
||||||
|
|
||||||
export function AuthBackground() {
|
export function AuthBackground() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.bg}>
|
<div className="absolute inset-0 z-0 overflow-hidden bg-[#fbf1f2]">
|
||||||
<Image
|
<Image
|
||||||
src="/images/auth/bg-login.png"
|
src="/images/auth/bg-login.png"
|
||||||
alt=""
|
alt=""
|
||||||
fill
|
fill
|
||||||
priority
|
priority
|
||||||
sizes="(max-width: 540px) 100vw, 540px"
|
sizes="(max-width: 540px) 100vw, 540px"
|
||||||
className={styles.image}
|
className="object-cover object-center"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 视觉规格(与 Dart 对齐):
|
|
||||||
* - panelShell 包裹整个面板(position: relative)
|
|
||||||
*/
|
|
||||||
.panelShell {
|
|
||||||
position: relative;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
|
|||||||
|
|
||||||
import { AuthEmailPanel } from "./auth-email-panel";
|
import { AuthEmailPanel } from "./auth-email-panel";
|
||||||
import { AuthFacebookPanel } from "./auth-facebook-panel";
|
import { AuthFacebookPanel } from "./auth-facebook-panel";
|
||||||
import styles from "./auth-panel.module.css";
|
|
||||||
|
|
||||||
export function AuthPanel() {
|
export function AuthPanel() {
|
||||||
const state = useAuthState();
|
const state = useAuthState();
|
||||||
@@ -29,7 +28,7 @@ export function AuthPanel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.panelShell}>
|
<div className="relative flex min-h-0 w-full flex-auto flex-col">
|
||||||
<BackButton onClick={handleBack} />
|
<BackButton onClick={handleBack} />
|
||||||
|
|
||||||
{state.authPanelMode === "facebook" ? (
|
{state.authPanelMode === "facebook" ? (
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
/* auth-screen.module.css
|
|
||||||
* 与 splash-screen.module.css 同款结构(MobileShell 顶层 + .wrapper + .content)
|
|
||||||
* 移动端宽度约束由 ResponsiveMobileShell / MobileShell 统一提供。
|
|
||||||
*/
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
min-height: var(--app-viewport-height, 100dvh);
|
|
||||||
background: #fbf1f2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
display: flex;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
padding:
|
|
||||||
calc(var(--page-padding-y, var(--spacing-lg)) + var(--app-safe-top, 0px))
|
|
||||||
calc(var(--page-padding-x, var(--spacing-lg)) + var(--app-safe-right, 0px))
|
|
||||||
calc(var(--page-padding-y, var(--spacing-lg)) + var(--app-safe-bottom, 0px))
|
|
||||||
calc(var(--page-padding-x, var(--spacing-lg)) + var(--app-safe-left, 0px));
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* 邮箱登录/注册表单样式
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 视觉规格(与 Dart 对齐):
|
|
||||||
* - 字段间距 12px(Dart AppSpacing.md)
|
|
||||||
* - 错误横幅与主按钮之间 12px
|
|
||||||
*/
|
|
||||||
.form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--spacing-md);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
import { AuthTextField } from "./auth-text-field";
|
import { AuthTextField } from "./auth-text-field";
|
||||||
import { AuthPrimaryButton } from "./auth-primary-button";
|
import { AuthPrimaryButton } from "./auth-primary-button";
|
||||||
import { AuthErrorMessage } from "./auth-error-message";
|
import { AuthErrorMessage } from "./auth-error-message";
|
||||||
import styles from "./email-form.module.css";
|
|
||||||
import { AppEnvUtil, Logger } from "@/utils";
|
import { AppEnvUtil, Logger } from "@/utils";
|
||||||
|
|
||||||
const log = new Logger("AppAuthComponentsEmailLoginForm");
|
const log = new Logger("AppAuthComponentsEmailLoginForm");
|
||||||
@@ -76,7 +75,7 @@ export function EmailLoginForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className={styles.form}
|
className="flex w-full flex-col gap-md"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
submit();
|
submit();
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
import { AuthTextField } from "./auth-text-field";
|
import { AuthTextField } from "./auth-text-field";
|
||||||
import { AuthPrimaryButton } from "./auth-primary-button";
|
import { AuthPrimaryButton } from "./auth-primary-button";
|
||||||
import { AuthErrorMessage } from "./auth-error-message";
|
import { AuthErrorMessage } from "./auth-error-message";
|
||||||
import styles from "./email-form.module.css";
|
|
||||||
import { Logger } from "@/utils";
|
import { Logger } from "@/utils";
|
||||||
|
|
||||||
const log = new Logger("AppAuthComponentsEmailRegisterForm");
|
const log = new Logger("AppAuthComponentsEmailRegisterForm");
|
||||||
@@ -112,7 +111,7 @@ export function EmailRegisterForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className={styles.form}
|
className="flex w-full flex-col gap-md"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
submit();
|
submit();
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
.slot {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
min-height: var(--button-height);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user