Files
writer-work-flow/apps/web/components/AppShell.tsx
Yaojia Wang 61a6931bb1 refactor(frontend): 删顶部「AI 工具条」,--chrome 归位 4rem(写作台 UX P0-3)
顶栏「AI 工具条」5 项全是重复左栏的导航链接,且让「写本章」同时是导航
Link 与生成动作两种相反含义。删掉后导航只归左栏,同时消灭最严重的三重复
+ 假「AI」标签 + 「写本章」双重含义,并省下 48px(--chrome 7rem→4rem)。
死代码 AiToolbar/AiToolbarMoreMenu/ai-tools 全仓仅 AppShell 引用,一并移除。
2026-07-10 17:43:46 +02:00

95 lines
3.0 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 { Settings } from "lucide-react";
import type { ActiveNav } from "@/lib/nav/items";
import { buttonClass, focusRing } from "@/lib/ui/variants";
import { CommandSearchButton } from "./command/CommandPaletteMount";
import { LeftNav } from "./LeftNav";
import { NavDrawer } from "./NavDrawer";
import { ThemeToggle } from "./ThemeToggle";
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"
style={{ ["--chrome" as string]: "4rem" }}
>
<a
href="#main"
className="sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:rounded focus:border focus:border-line focus:bg-panel focus:px-3 focus:py-2 focus:text-sm focus:text-ink focus:shadow-paper"
>
</a>
<header className="sticky top-0 z-30 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={`shrink-0 whitespace-nowrap rounded font-serif text-xl text-cinnabar ${focusRing}`}
aria-label="返回作品库"
>
</Link>
{title ? (
<span className="min-w-0 truncate font-serif text-lg text-ink">
{title}
</span>
) : null}
{subtitle ? (
<span className="hidden shrink-0 font-mono text-xs text-ink-soft sm:inline">
{subtitle}
</span>
) : null}
<nav
aria-label="快捷操作"
className="ml-auto flex shrink-0 items-center gap-2 text-sm"
>
<CommandSearchButton />
<ThemeToggle />
<Link
href="/settings/providers"
aria-label="设置"
title="设置"
className={buttonClass({
variant: "ghost",
size: "sm",
className: "border-transparent",
})}
>
<Settings className="h-4 w-4" aria-hidden="true" />
<span className="hidden sm:inline"></span>
</Link>
</nav>
</header>
<div className="flex">
<LeftNav projectId={projectId} activeNav={activeNav} />
<main
id="main"
tabIndex={-1}
className="min-h-[calc(100vh-var(--chrome,4rem))] min-w-0 flex-1 bg-bg"
>
{children}
</main>
</div>
</div>
);
}