minidocs

侧边栏

侧边栏由你自己写:遍历文档树,用 Sidebar 组件渲染每一项。结构、顺序和每一项的样子都在你的代码里。

完整的例子

---
import { Sidebar } from '@minidocs/astro/components';
import { navState } from '@minidocs/astro/runtime';
import { tree } from '../lib/docs';

const { id } = Astro.props;
const nav = navState(tree, id);
---

<Sidebar.Root id="sidebar" label="文档">
  <Sidebar.List>
    {tree.map(function item(node) {
      return (
        <Sidebar.Item>
          {node.children.length > 0 ? (
            <Sidebar.Group {...nav.of(node)}>
              <Fragment slot="label">{node.label}</Fragment>
              <Sidebar.List>{node.children.map(item)}</Sidebar.List>
            </Sidebar.Group>
          ) : (
            <Sidebar.Link {...nav.of(node)}>{node.label}</Sidebar.Link>
          )}
        </Sidebar.Item>
      );
    })}
  </Sidebar.List>
</Sidebar.Root>

tree.map 的回调起了名字 item,遇到有子节点的分组时,用 node.children.map(item) 渲染下一层,所以树有多少层都能渲染出来。多语言站点把 tree 换成 tree[locale]。

navState(tree, id) 记下当前页面在树里的位置,nav.of(node) 返回渲染一个节点要用的值:

字段 含义
href 页面或外部链接的地址,分组没有
current 这个节点是不是当前页面
open 当前页面是不是这个节点本身或在它下面

这些字段和组件的参数同名,所以可以直接展开。也可以改写其中的值,比如让某个分组始终展开:

<Sidebar.Group {...nav.of(node)} open>

每个组件的参数见组件与样式。

分组的几种样子

小标题

第一层的分组常常只是一个小标题,下面直接列出页面,不能折叠。用 Sidebar.Label 加 Sidebar.List。下面的写法在第一层用小标题,更深的层级用可折叠的分组:

{tree.map(function item(node) {
  return (
    <Sidebar.Item>
      {node.children.length === 0 ? (
        <Sidebar.Link {...nav.of(node)}>{node.label}</Sidebar.Link>
      ) : tree.includes(node) ? (
        <>
          <Sidebar.Label>{node.label}</Sidebar.Label>
          <Sidebar.List>{node.children.map(item)}</Sidebar.List>
        </>
      ) : (
        <Sidebar.Group {...nav.of(node)}>
          <Fragment slot="label">{node.label}</Fragment>
          <Sidebar.List>{node.children.map(item)}</Sidebar.List>
        </Sidebar.Group>
      )}
    </Sidebar.Item>
  );
})}

可折叠的分组

Sidebar.Group 渲染成可以折叠的分组,点击标题展开或收起,上面的完整例子用的就是它。分组的标题写在 label slot 里。

手风琴

给同一层的分组传相同的 name,展开一个时其他的会自动收起。有自己页面的分组不参与:

<Sidebar.Group {...nav.of(node)} name="sections">

有自己页面的分组

用 page(id, children) 定义的分组本身也是一个页面,nav.of(node) 会给它 href。它的标题在不同页面上表现不同:

当前页面 点击标题
其他页面 跳转到分组的页面,并展开
分组下面的页面 跳转到分组的页面
分组自己的页面 收起或展开

跨页面保持状态

从一个页面跳到另一个页面时,侧边栏会保持原来的样子:展开的分组和滚动位置都不变。当前页面所在的分组总是展开的,这样你总能在侧边栏里看到自己在哪。

窄屏下的菜单

Sidebar.Trigger 是打开和关闭侧边栏的按钮,target 是侧边栏的 id:

<Sidebar.Trigger target="sidebar" aria-label="菜单">☰</Sidebar.Trigger>
<Sidebar.Root id="sidebar" label="文档">...</Sidebar.Root>

侧边栏放在 Layout.Sidebar 里时,默认样式在窄屏下把它变成从左侧滑出的抽屉,按 Esc 或点击外面会关闭,见页面布局。

本页目录
搜索范围
输入关键词开始搜索