feat(auth): introduce immersive split-screen login design
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import a from "@/styles/account.module.css";
|
||||
import { ThemeToggle } from "./ThemeToggle";
|
||||
import { Brand } from "./Brand";
|
||||
import Head from "next/head";
|
||||
@@ -191,11 +192,10 @@ export default function GuidanceShell({
|
||||
}
|
||||
if (standalone) return (
|
||||
<AccountContext.Provider value={{ user, loading, error, refresh }}>
|
||||
<div className={s.accountPage}>
|
||||
<div className={a.page}>
|
||||
<Head><title>{`${title} · 啡跃`}</title></Head>
|
||||
<a className={s.skipLink} href="#account-content">跳到正文</a>
|
||||
<header className={s.accountHeader}>
|
||||
<Link href="/" aria-label="啡跃首页"><Brand /></Link>
|
||||
<header className={a.header}>
|
||||
<div><Link href="/">返回首页</Link><ThemeToggle /></div>
|
||||
</header>
|
||||
<main id="account-content">{children}</main>
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { Brand } from "@/components/Brand";
|
||||
import a from "@/styles/account.module.css";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState, type FormEvent } from "react";
|
||||
import {
|
||||
ArrowRight,
|
||||
BookOpen,
|
||||
CheckCircle2,
|
||||
Eye,
|
||||
EyeOff,
|
||||
GitBranch,
|
||||
Link2,
|
||||
LogOut,
|
||||
MailCheck,
|
||||
} from "lucide-react";
|
||||
@@ -111,43 +110,23 @@ function AccountContent() {
|
||||
setFeedback(null);
|
||||
}
|
||||
return (
|
||||
<div className={s.accountLayout}>
|
||||
<section className={s.accountIntro}>
|
||||
<span className={s.eyebrow}>YOUR KNOWLEDGE, CONNECTED</span>
|
||||
<h1>
|
||||
让有用的知识,
|
||||
<br />
|
||||
成为下一次行动的起点。
|
||||
</h1>
|
||||
<p>
|
||||
用邮箱建立你的知识空间。把工作方法写成独立文档,让 Agent
|
||||
在需要的时候找到它。
|
||||
</p>
|
||||
<div className={s.accountFeatures}>
|
||||
<div>
|
||||
<BookOpen size={18} />
|
||||
<div>
|
||||
<strong>每篇文档,都能独立使用</strong>
|
||||
<p>从当前任务出发,无需加载整个集合。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<GitBranch size={18} />
|
||||
<div>
|
||||
<strong>每次更新,都有固定版本</strong>
|
||||
<p>历史引用保持可读,修改始终有迹可循。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Link2 size={18} />
|
||||
<div>
|
||||
<strong>知识之间,按条件连接</strong>
|
||||
<p>需要更多背景时,再沿有用的链接继续阅读。</p>
|
||||
</div>
|
||||
<div className={a.layout}>
|
||||
<section className={a.intro} data-theme="home-dark" aria-label="啡跃创作空间">
|
||||
<Link className={a.brand} href="/" aria-label="啡跃首页"><Brand /></Link>
|
||||
<div className={a.story}>
|
||||
<p className={a.eyebrow}>A SPACE FOR YOUR NEXT IDEA</p>
|
||||
<h1>给想法留白,<br />让灵感有形。</h1>
|
||||
<p className={a.description}>收集一闪而过的灵感,把有用的知识连接起来。下一件作品,从这里开始。</p>
|
||||
<div className={a.art} aria-hidden="true">
|
||||
<div className={a.orbit} />
|
||||
<div className={a.idea}><span>01 / THE IDEA</span><strong>留住清晨<br />的一束光。</strong><i>灵感片段 · 随手记下</i></div>
|
||||
<div className={a.work}><span>02 / IN THE MAKING</span><div className={a.artwork} /><strong>光的形状</strong><i>让一个念头,慢慢成形。</i></div>
|
||||
<span className={a.artCaption}>COLLECT. CONNECT. CREATE.</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className={a.signature}>啡跃 Endoleap <span>为下一次创作,留一个起点。</span></p>
|
||||
</section>
|
||||
<section className={s.authCard} aria-label="邮箱账户">
|
||||
<section className={`${s.authCard} ${a.form}`} aria-label="邮箱账户">
|
||||
<h2>
|
||||
{account.user
|
||||
? "你的账户"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
.page { min-height: 100svh; background: var(--surface); color: var(--foreground); }
|
||||
.header { position: absolute; z-index: 2; top: 28px; right: 36px; }
|
||||
.header > div { display: flex; align-items: center; gap: 20px; font-size: 13px; color: var(--muted-foreground); }
|
||||
.header a:hover { color: var(--foreground-strong); }
|
||||
.layout { display: grid; grid-template-columns: 46% minmax(0, 1fr); min-height: 100svh; }
|
||||
.intro { position: relative; isolation: isolate; display: flex; flex-direction: column; min-width: 0; padding: 38px clamp(32px, 5vw, 80px) 30px; overflow: hidden; background: var(--background); color: var(--foreground); }
|
||||
.intro::before { content: ''; position: absolute; z-index: -1; inset: 0; background: radial-gradient(ellipse at 0% 35%, color-mix(in srgb, var(--el-deep-mocha) 85%, transparent), transparent 60%), radial-gradient(ellipse at 100% 92%, color-mix(in srgb, var(--primary) 45%, transparent), transparent 65%); }
|
||||
.brand { align-self: flex-start; }
|
||||
.story { margin: auto 0; padding-top: 64px; }
|
||||
.eyebrow { margin: 0 0 20px; font-size: 10px; letter-spacing: .18em; color: var(--muted-foreground); line-height: 1.7; }
|
||||
.story h1 { margin: 0 0 22px; font-size: clamp(32px, 3.3vw, 50px); font-weight: 600; line-height: 1.3; letter-spacing: -.035em; color: var(--foreground-strong); }
|
||||
.description { margin: 0; max-width: 340px; font-size: 15px; line-height: 1.9; color: var(--foreground); }
|
||||
.signature { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 32px 0 0; font-size: 11px; line-height: 1.7; color: var(--muted-foreground); }
|
||||
.signature span { opacity: .8; }
|
||||
.art { position: relative; height: 300px; margin: 28px -12px 0; pointer-events: none; }
|
||||
.orbit { position: absolute; width: 245px; height: 245px; left: 15%; top: 5%; border: 1px solid color-mix(in srgb, var(--foreground) 18%, transparent); border-radius: 50%; }
|
||||
.orbit::after { content: ''; position: absolute; inset: 25px -35px; border: inherit; border-radius: 50%; transform: rotate(-38deg); }
|
||||
.idea, .work { position: absolute; display: flex; flex-direction: column; border: 1px solid color-mix(in srgb, var(--foreground) 24%, transparent); border-radius: 14px; box-shadow: 0 20px 50px var(--shadow); }
|
||||
.idea { left: 0; top: 42px; width: 48%; min-height: 196px; padding: 22px 18px; transform: rotate(-8deg); background: color-mix(in srgb, var(--surface) 78%, transparent); backdrop-filter: blur(16px); }
|
||||
.idea span, .work > span { font-size: 8px; letter-spacing: .12em; line-height: 1.6; }
|
||||
.idea strong { margin: 24px 0 18px; font-size: clamp(18px, 1.8vw, 26px); font-weight: 500; line-height: 1.5; }
|
||||
.idea i, .work i { font-size: 9px; font-style: normal; line-height: 1.7; opacity: .72; }
|
||||
.work { right: 0; top: 15px; width: 51%; padding: 18px; transform: rotate(8deg); background: var(--el-cream); color: var(--el-espresso); }
|
||||
.artwork { height: 110px; margin: 16px 0 14px; overflow: hidden; border-radius: 100px 100px 8px 8px; background: radial-gradient(ellipse at 75% 20%, var(--el-cream), transparent 60%), linear-gradient(135deg, var(--el-deep-mocha), var(--el-espresso)); }
|
||||
.work strong { margin-bottom: 6px; font-size: 19px; font-weight: 500; }
|
||||
.artCaption { position: absolute; bottom: 0; left: 0; right: 0; text-align: center; font-size: 8px; letter-spacing: .2em; color: var(--muted-foreground); }
|
||||
.page .form { align-self: center; width: min(400px, calc(100% - 96px)); min-width: 0; margin: 116px auto 80px; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
|
||||
.page .form h2 { font-size: 28px; font-weight: 600; text-align: center; letter-spacing: -.04em; }
|
||||
.page .form > p:first-of-type { font-size: 14px; text-align: center; margin: 10px 0 32px; }
|
||||
.page .form label { font-size: 13px; font-weight: 500; }
|
||||
.page .form input { min-height: 46px; font-size: 14px; background: var(--surface); border: 1px solid var(--input); border-radius: 8px; box-shadow: 0 1px 2px var(--shadow); }
|
||||
.page .form nav { background: var(--surface-muted); padding: 4px; margin-bottom: 28px; border: 1px solid var(--border); border-radius: 9px; }
|
||||
.page .form nav button { min-height: 36px; font-size: 13px; }
|
||||
.page .form button[type='submit'] { min-height: 46px; font-size: 14px; border-radius: 8px; margin-top: 8px; }
|
||||
.page .form form + div { margin-top: 22px; }
|
||||
.page .form form + div button { font-size: 12px; }
|
||||
.page .form > p:last-child { margin-top: 32px !important; font-size: 12px; line-height: 1.8; }
|
||||
@media (min-width: 1500px) { .story { max-width: 480px; width: 100%; margin-left: auto; margin-right: auto; } .art { height: 330px; } .brand, .signature { margin-left: 0; } }
|
||||
@media (max-width: 1000px) { .intro { padding-left: 28px; padding-right: 28px; } .story h1 { font-size: 34px; } .description { font-size: 14px; } .page .form { width: min(380px, calc(100% - 64px)); } .header { right: 28px; } }
|
||||
@media (max-width: 760px) {
|
||||
.header { position: static; display: flex; justify-content: flex-end; padding: 16px 20px; }
|
||||
.layout { display: flex; flex-direction: column; min-height: auto; }
|
||||
.intro { margin: 0 16px; padding: 24px; border-radius: 16px; }
|
||||
.brand { margin-bottom: 28px; }
|
||||
.story { margin: 0; padding: 0; }
|
||||
.eyebrow { margin-bottom: 12px; font-size: 9px; }
|
||||
.story h1 { font-size: 30px; margin-bottom: 14px; }
|
||||
.description { max-width: 420px; font-size: 13px; line-height: 1.8; }
|
||||
.art, .signature { display: none; }
|
||||
.page .form { width: min(400px, calc(100% - 48px)); margin: 40px auto 48px; }
|
||||
.page .form h2 { font-size: 25px; }
|
||||
}
|
||||
@@ -1678,70 +1678,11 @@
|
||||
height: 31px;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
.accountLayout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 400px;
|
||||
max-width: 1000px;
|
||||
gap: 80px;
|
||||
align-items: center;
|
||||
margin: 40px auto 64px;
|
||||
}
|
||||
.accountIntro {
|
||||
min-width: 0;
|
||||
max-width: 460px;
|
||||
padding: 16px 20px 16px 8px;
|
||||
}
|
||||
.accountIntro > .eyebrow {
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
font-size: 11px;
|
||||
letter-spacing: .14em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.accountIntro h1 {
|
||||
margin: 0 0 22px;
|
||||
font-size: 36px;
|
||||
line-height: 1.45;
|
||||
letter-spacing: -.035em;
|
||||
font-weight: 650;
|
||||
text-wrap: balance;
|
||||
}
|
||||
.accountIntro > p {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
line-height: 1.9;
|
||||
color: var(--muted-foreground);
|
||||
max-width: 380px;
|
||||
}
|
||||
.accountFeatures {
|
||||
display: grid;
|
||||
gap: 22px;
|
||||
margin-top: 32px;
|
||||
padding-top: 26px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.accountFeatures > div {
|
||||
display: grid;
|
||||
grid-template-columns: 20px minmax(0, 1fr);
|
||||
align-items: start;
|
||||
gap: 14px;
|
||||
}
|
||||
.accountFeatures svg {
|
||||
color: var(--muted-foreground);
|
||||
margin-top: 3px;
|
||||
}
|
||||
.accountFeatures strong {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
font-weight: 600;
|
||||
}
|
||||
.accountFeatures p {
|
||||
margin: 4px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--muted-foreground);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.authCard {
|
||||
padding: 28px;
|
||||
border: 1px solid var(--line);
|
||||
@@ -1926,10 +1867,7 @@
|
||||
grid-template-columns: minmax(0, 1fr) 230px;
|
||||
gap: 20px;
|
||||
}
|
||||
.accountLayout {
|
||||
gap: 48px;
|
||||
grid-template-columns: minmax(0, 1fr) 370px;
|
||||
}
|
||||
|
||||
.protocolLayout {
|
||||
grid-template-columns: minmax(0, 1fr) 190px;
|
||||
}
|
||||
@@ -1969,34 +1907,9 @@
|
||||
.protocolLayout > aside {
|
||||
display: none;
|
||||
}
|
||||
.accountLayout {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 430px;
|
||||
margin: 15px auto 40px;
|
||||
gap: 25px;
|
||||
}
|
||||
.accountIntro {
|
||||
padding: 0 4px;
|
||||
max-width: none;
|
||||
}
|
||||
.accountIntro > .eyebrow {
|
||||
margin-bottom: 12px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.accountIntro h1 {
|
||||
font-size: 26px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.accountFeatures {
|
||||
display: none;
|
||||
}
|
||||
.accountIntro > p {
|
||||
max-width: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
.accountIntro h1 br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.topbarProtocol {
|
||||
display: none;
|
||||
}
|
||||
@@ -2307,16 +2220,8 @@
|
||||
.authCard {
|
||||
padding: 24px;
|
||||
}
|
||||
.accountLayout {
|
||||
margin-top: 8px;
|
||||
gap: 24px;
|
||||
}
|
||||
.accountIntro h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.accountIntro > p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
.modalBody {
|
||||
padding: 23px;
|
||||
}
|
||||
@@ -2382,14 +2287,3 @@
|
||||
.primaryButton,.primaryButton:hover{color:var(--primary-foreground);background:var(--primary)}
|
||||
.primaryButton:hover{background:var(--primary-hover)}
|
||||
.primaryButton:disabled{background:var(--disabled-background);color:var(--disabled-foreground)}
|
||||
|
||||
/* Authentication has its own public page, without workspace navigation. */
|
||||
.accountPage { min-height: 100vh; background: var(--background); color: var(--foreground); }
|
||||
.accountHeader { max-width: 1200px; margin: 0 auto; padding: 24px 32px; display: flex; align-items: center; justify-content: space-between; gap: 20px; }
|
||||
.accountHeader a { color: var(--muted-foreground); text-decoration: none; }
|
||||
.accountHeader > div { display: flex; align-items: center; gap: 20px; font-size: 13px; }
|
||||
.accountPage > main { max-width: 1120px; margin: 0 auto; padding: 48px 32px 72px; }
|
||||
@media (max-width: 650px) {
|
||||
.accountHeader { padding: 20px; }
|
||||
.accountPage > main { padding: 20px 20px 48px; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user