feat(frontend): 左栏 10 项按写作/资料库/审阅/更多分组(UX P2-1)

navSections(projectId?) 纯函数把平铺项目项归为四组,NavItems 复用「本作」小标题模式逐组渲染;链接/路由/激活键不变,工具箱收进「更多」不丢入口。
This commit is contained in:
Yaojia Wang
2026-07-10 18:14:41 +02:00
parent e9c5502c2d
commit 3c87b01379
3 changed files with 108 additions and 26 deletions

View File

@@ -1,5 +1,6 @@
"use client";
import { Fragment } from "react";
import Link from "next/link";
import {
Blocks,
@@ -19,9 +20,8 @@ import {
import { usePathname } from "next/navigation";
import {
GLOBAL_NAV_ITEMS,
isNavItemActive,
projectNavItems,
navSections,
type ActiveNav,
type NavItem,
} from "@/lib/nav/items";
@@ -36,35 +36,32 @@ interface NavItemsProps {
}
// 导航条目列表(桌面静态侧栏与移动抽屉共用,避免渲染漂移)。
// 项目内页把 10 项按 写作/资料库/审阅/更多 分组P2-1每组一个小标题全局组无标题直显于顶部。
export function NavItems({ projectId, activeNav, onNavigate }: NavItemsProps) {
const pathname = usePathname() ?? "/";
const scoped = projectId ? projectNavItems(projectId) : [];
const sections = navSections(projectId);
return (
<ul className="flex flex-col gap-1 px-2">
{GLOBAL_NAV_ITEMS.map((item) => (
<NavLink
key={item.label}
item={item}
active={isNavItemActive(item, { pathname, activeNav })}
onNavigate={onNavigate}
/>
))}
{scoped.length > 0 ? (
<li
className="mt-3 px-3 pb-1 text-xs font-semibold uppercase tracking-wide text-ink-soft/60"
aria-hidden="true"
>
</li>
) : null}
{scoped.map((item) => (
<NavLink
key={item.label}
item={item}
active={isNavItemActive(item, { pathname, activeNav })}
onNavigate={onNavigate}
/>
{sections.map((section) => (
<Fragment key={section.label ?? "__global"}>
{section.label !== null ? (
<li
className="mt-3 px-3 pb-1 text-xs font-semibold uppercase tracking-wide text-ink-soft/60"
aria-hidden="true"
>
{section.label}
</li>
) : null}
{section.items.map((item) => (
<NavLink
key={item.label}
item={item}
active={isNavItemActive(item, { pathname, activeNav })}
onNavigate={onNavigate}
/>
))}
</Fragment>
))}
</ul>
);