Files
writer-work-flow/apps/web/components/AppShell.tsx
Yaojia Wang 9b893a6c61 feat(ux): M1/M2 移动端可用 — 导航汉堡抽屉 + 写作工具条不溢出
M1 左导航响应式抽屉:抽出 lib/nav/items.ts(条目数据+激活判定,纯逻辑+vitest)
共用于桌面静态侧栏(hidden lg:block)与移动汉堡抽屉。新增通用 Drawer(遮罩/
Esc 关闭/打开聚焦,复用 CommandPalette a11y 模式)+ NavDrawer + NavItems;
LeftNav 改 <lg 隐藏,AppShell 顶栏加汉堡(aria-label 打开导航)。

M2 写作工具条不溢出 + 移动端可达章节/助手:Toolbar 改 flex-wrap,390px 不再
横切「尚未保存」;ChapterList/ChapterAssistant 抽出 *Content,Workbench 经
左/右 Drawer 在 <lg 触达目录/助手。

实景 390px 复验(browse):汉堡显示/静态导航隐藏/抽屉开合聚焦+Esc、工具条
两行不溢出、助手抽屉真注入面板。门禁:lint/typecheck 干净 · vitest 177 · build OK。
2026-06-20 11:26:14 +02:00

60 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Link from "next/link";
import type { ReactNode } from "react";
import type { ActiveNav } from "@/lib/nav/items";
import { LeftNav } from "./LeftNav";
import { NavDrawer } from "./NavDrawer";
interface AppShellProps {
children: ReactNode;
// 顶栏右侧的上下文信息(如作品名 / 进度)。
title?: string;
subtitle?: string;
// 项目内页给出 projectId → 左导航展开项目级入口(大纲/伏笔/审稿UX §3.1)。
projectId?: string;
// 当前激活的项目级入口键(用于高亮)。
activeNav?: ActiveNav;
}
// 全局外壳:顶栏(64px) + 左导航 + 主区UX §5.1)。
export function AppShell({
children,
title,
subtitle,
projectId,
activeNav,
}: AppShellProps) {
return (
<div className="min-h-screen">
<header className="flex h-16 items-center gap-4 border-b border-line bg-panel px-4 sm:px-6">
<NavDrawer projectId={projectId} activeNav={activeNav} />
<Link
href="/"
className="font-serif text-xl text-cinnabar"
aria-label="返回作品库"
>
</Link>
{title ? (
<span className="font-serif text-lg text-ink">{title}</span>
) : null}
{subtitle ? (
<span className="font-mono text-xs text-ink-soft">{subtitle}</span>
) : null}
<nav className="ml-auto flex items-center gap-4 text-sm">
<Link
href="/settings/providers"
className="text-ink-soft hover:text-cinnabar"
>
</Link>
</nav>
</header>
<div className="flex">
<LeftNav projectId={projectId} activeNav={activeNav} />
<main className="min-h-[calc(100vh-4rem)] flex-1 bg-bg">{children}</main>
</div>
</div>
);
}