Files
stash/stash-web/src/components/sidebar/CategoryNav.tsx
T

80 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 { useState } from 'react'
import { NAV_GROUPS, NAV_TOP_LEVEL, type NavTarget } from '../../data/nav'
/**
* 分类导航树:顶层直达链接 + 可折叠分组。
* 点击叶子节点不跳转页面,而是把目标(分类 + 可选分组)交给父组件的 onNavigate,
* 由父组件切换右侧的明细视图。
*/
type CategoryNavProps = {
/** 当前明细视图的分类 / 分组,用于高亮 */
activeCategoryId?: string
activeGroupId?: string
onNavigate: (target: NavTarget) => void
}
export function CategoryNav({ activeCategoryId, activeGroupId, onNavigate }: CategoryNavProps) {
const [openGroups, setOpenGroups] = useState<string[]>([])
const toggle = (id: string) => {
setOpenGroups((previous) =>
previous.includes(id) ? previous.filter((item) => item !== id) : [...previous, id],
)
}
const isOpen = (id: string) => openGroups.includes(id)
return (
<nav className="nav-card card-box" aria-label="站点分类">
<ul className="nav-group">
{NAV_TOP_LEVEL.map((leaf) => (
<li className="nav-item" key={leaf.id}>
<button
type="button"
className={`nav-link${
activeCategoryId === leaf.target.categoryId && activeGroupId === undefined
? ' active'
: ''
}`}
onClick={() => onNavigate(leaf.target)}
>
<span>{leaf.label}</span>
</button>
</li>
))}
{NAV_GROUPS.map((group) => (
<li className={`nav-item${isOpen(group.id) ? ' open' : ''}`} key={group.id}>
<button
type="button"
className="nav-link has-children"
aria-expanded={isOpen(group.id)}
onClick={() => toggle(group.id)}
>
<span>{group.label}</span>
</button>
{/* 用 grid-template-rows 做高度动画:不需要猜 max-height,
也不会在过渡期间出现滚动条 */}
<div className={`submenu-wrap${isOpen(group.id) ? ' is-open' : ''}`}>
<ul className="submenu">
{group.leaves.map((leaf) => (
<li key={leaf.id}>
<button
type="button"
className={`nav-link${activeGroupId === leaf.target.groupId ? ' active' : ''}`}
onClick={() => onNavigate(leaf.target)}
>
<span>{leaf.label}</span>
</button>
</li>
))}
</ul>
</div>
</li>
))}
</ul>
</nav>
)
}