Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a45d43f5f7 | |||
| 5b68c5b84e |
@@ -48,9 +48,11 @@ export const useGuidanceAccount = () => useContext(AccountContext);
|
||||
export default function GuidanceShell({
|
||||
children,
|
||||
title = "探索文档",
|
||||
standalone = false,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
title?: string;
|
||||
standalone?: boolean;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const dialog = useRef<HTMLDialogElement>(null);
|
||||
@@ -187,6 +189,19 @@ export default function GuidanceShell({
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (standalone) return (
|
||||
<AccountContext.Provider value={{ user, loading, error, refresh }}>
|
||||
<div className={s.accountPage}>
|
||||
<Head><title>{`${title} · 啡跃`}</title></Head>
|
||||
<a className={s.skipLink} href="#account-content">跳到正文</a>
|
||||
<header className={s.accountHeader}>
|
||||
<Link href="/" aria-label="啡跃首页"><Brand /></Link>
|
||||
<div><Link href="/">返回首页</Link><ThemeToggle /></div>
|
||||
</header>
|
||||
<main id="account-content">{children}</main>
|
||||
</div>
|
||||
</AccountContext.Provider>
|
||||
);
|
||||
return (
|
||||
<AccountContext.Provider value={{ user, loading, error, refresh }}>
|
||||
<div className={s.site}>
|
||||
|
||||
@@ -3,5 +3,5 @@ export function ThemeToggle() {
|
||||
const [dark, setDark] = useState(false);
|
||||
const [ready, setReady] = useState(false);
|
||||
useEffect(() => { const sync = () => setDark(document.documentElement.dataset.mode === 'dark'); sync(); setReady(true); window.addEventListener('endoleap-theme', sync); return () => window.removeEventListener('endoleap-theme', sync); }, []);
|
||||
return <button type="button" data-theme-ready={ready} className="endoleap-theme-toggle" aria-label="切换明暗主题" title={dark ? '切换浅色模式' : '切换深色模式'} onClick={() => { const mode = document.documentElement.dataset.mode === 'dark' ? 'light' : 'dark'; const scope = document.documentElement.dataset.theme?.startsWith('canvas-') ? 'canvas' : 'home'; document.documentElement.dataset.mode = mode; document.documentElement.dataset.theme = `${scope}-${mode}`; try { localStorage.setItem('endoleap.theme', mode); } catch {} window.dispatchEvent(new Event('endoleap-theme')); }}>◐<span>{dark ? '浅色' : '深色'}</span></button>;
|
||||
return <button type="button" data-theme-ready={ready} className="endoleap-theme-toggle" aria-label="切换明暗主题" title={dark ? '切换浅色模式' : '切换深色模式'} onClick={() => { const mode = document.documentElement.dataset.mode === 'dark' ? 'light' : 'dark'; const scope = document.documentElement.dataset.theme?.startsWith('canvas-') ? 'canvas' : 'home'; document.documentElement.dataset.mode = mode; document.documentElement.dataset.theme = `${scope}-${mode}`; try { localStorage.setItem('endoleap.theme', mode); } catch {} window.dispatchEvent(new Event('endoleap-theme')); }}><span aria-hidden="true">◐</span></button>;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ function localNext(value: string | string[] | undefined) {
|
||||
}
|
||||
export default function AccountPage() {
|
||||
return (
|
||||
<GuidanceShell title="邮箱账户">
|
||||
<GuidanceShell title="登录与注册" standalone>
|
||||
<AccountContent />
|
||||
</GuidanceShell>
|
||||
);
|
||||
|
||||
@@ -8,11 +8,11 @@ body{margin:0}
|
||||
[data-theme$="-dark"] .endoleap-mark-dark{display:block!important}
|
||||
.endoleap-wordmark{display:flex!important;flex-direction:column;font-size:17px!important;color:var(--foreground-strong)!important;letter-spacing:.02em!important;margin:0!important;gap:3px}
|
||||
.endoleap-wordmark small{display:block;font-size:9px;font-weight:500;letter-spacing:.08em;color:var(--muted-foreground)}
|
||||
button.endoleap-theme-toggle{display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid var(--border);background:var(--surface);color:var(--foreground);border-radius:8px;padding:7px 9px;font-size:12px;line-height:1.2;flex-shrink:0;cursor:pointer}
|
||||
button.endoleap-theme-toggle{display:inline-flex;align-items:center;justify-content:center;gap:5px;border:0;background:transparent;color:var(--muted-foreground);border-radius:8px;padding:8px;width:32px;height:32px;font-size:16px;line-height:1.2;flex-shrink:0;cursor:pointer}
|
||||
button.endoleap-theme-toggle:hover{background:var(--row-hover)}
|
||||
:where(a,button,input,textarea,select):focus-visible{outline:2px solid var(--ring);outline-offset:3px}
|
||||
::selection{background:var(--selection);color:var(--foreground)}
|
||||
@media(max-width:600px){.endoleap-theme-toggle span{display:none}.endoleap-brand{gap:5px}.endoleap-brand .endoleap-mark{width:26px;height:26px}.endoleap-wordmark{font-size:14px!important}}
|
||||
@media(max-width:600px){.endoleap-theme-toggle span{display:inline}.endoleap-brand{gap:5px}.endoleap-brand .endoleap-mark{width:26px;height:26px}.endoleap-wordmark{font-size:14px!important}}
|
||||
|
||||
button:disabled{cursor:default}
|
||||
input,textarea,select{accent-color:var(--primary)}
|
||||
|
||||
@@ -2380,3 +2380,14 @@
|
||||
.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; }
|
||||
}
|
||||
|
||||
@@ -102,7 +102,11 @@ export async function verifyGuidanceWorkspaceUI(base: string, browser: Browser)
|
||||
try {
|
||||
const navigation = await (reload ? page.reload({waitUntil:"commit"}) : page.goto(url,{waitUntil:"commit"}));
|
||||
assert.ok(navigation?.ok(), "Navigation returns a successful document");
|
||||
await page.getByText(signedIn ? "editor@example.com" : "登录你的账户",{exact:true}).first().waitFor({state:"attached"});
|
||||
if (new URL(url).pathname === "/account") {
|
||||
await page.getByRole("heading", { name: signedIn ? "你的账户" : "欢迎回来", exact: true }).waitFor();
|
||||
} else {
|
||||
await page.getByText(signedIn ? "editor@example.com" : "登录你的账户",{exact:true}).first().waitFor({state:"attached"});
|
||||
}
|
||||
assert.ok(sessionReplies > previousSessionReplies, "The new document requests its account fixture and renders the resulting account state");
|
||||
} catch (error) {
|
||||
const probeStarted=Date.now();
|
||||
@@ -155,6 +159,9 @@ export async function verifyGuidanceWorkspaceUI(base: string, browser: Browser)
|
||||
fullPage: true,
|
||||
});
|
||||
await navigate(base + "/account");
|
||||
assert.equal(await page.getByRole("complementary").count(), 0, "Account page has no workspace sidebar");
|
||||
assert.equal(await page.getByRole("link", { name: "创建文档", exact: true }).count(), 0);
|
||||
await page.getByRole("link", { name: "返回首页", exact: true }).waitFor();
|
||||
await page.getByRole("button", { name: "创建账户", exact: true }).click();
|
||||
await page.getByRole("heading", { name: "创建你的账户" }).waitFor();
|
||||
await page
|
||||
|
||||
Reference in New Issue
Block a user