Files
writer-work-flow/apps/web/components/workbench/ChapterList.tsx

85 lines
2.7 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 { buildChapterEntries, type ChapterEntry } from "@/lib/workbench/chapter";
interface ChapterListProps {
projectId: string;
// 大纲章节(来自 GET .../outline无大纲时为空当前章会被并入并去重。
chapters: ChapterEntry[];
currentChapterNo: number;
}
// 左栏目录UX §6.3):列出大纲全部章节 + 当前章,点击切换写作章号(`?chapter=N`)。
// 桌面 aside 包裹;移动端经 Workbench 抽屉复用 ChapterListContent。
export function ChapterList({
projectId,
chapters,
currentChapterNo,
}: ChapterListProps) {
return (
<aside className="hidden border-r border-line bg-panel py-4 xl:block">
<ChapterListContent
projectId={projectId}
chapters={chapters}
currentChapterNo={currentChapterNo}
/>
</aside>
);
}
export function ChapterListContent({
projectId,
chapters,
currentChapterNo,
}: ChapterListProps) {
const entries = buildChapterEntries(chapters, currentChapterNo);
const hasOutline = chapters.length > 0;
return (
<>
<h2 className="px-4 text-xs font-semibold uppercase tracking-wide text-ink-soft">
</h2>
<ul className="mt-2">
{entries.map((entry) => {
const active = entry.no === currentChapterNo;
return (
<li key={entry.no}>
<Link
href={`/projects/${projectId}/write?chapter=${entry.no}`}
aria-current={active ? "page" : undefined}
className={
active
? "flex flex-col gap-0.5 border-l-2 border-cinnabar bg-[var(--color-cinnabar-wash)] px-4 py-2 text-sm text-cinnabar"
: "flex flex-col gap-0.5 border-l-2 border-transparent px-4 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar"
}
>
<span className="flex items-center gap-2">
{active ? <span aria-hidden="true"></span> : null}{" "}
{entry.no}
</span>
{entry.title ? (
<span className="truncate text-xs text-ink-soft">
{entry.title}
</span>
) : null}
</Link>
</li>
);
})}
</ul>
{!hasOutline ? (
<p className="mt-4 px-4 text-xs text-ink-soft/70">
<Link
href={`/projects/${projectId}/outline`}
className="text-cinnabar hover:underline"
>
</Link>
</p>
) : null}
</>
);
}