跳到正文

Menu 菜单

Menu 是纵向的导航菜单,比如应用或文档站的侧边栏:带图标的行、原地展开的子菜单、带标题的分组和分割线,同时只有一行处于选中状态。它渲染成 <nav> 地标,请给它加上 aria-label。从按钮弹出的菜单请用 Dropdown。

演示

基础用法

选项是一棵树:普通行 { key, label, icon? }、子菜单(带 children 的行)、分组(type: "group")和分割线(type: "divider")。选中行所在的子菜单默认展开,包含选中行的子菜单也会被标出。

链接和路由

带 href 的行渲染成链接,选中时带 aria-current="page"。renderLink 用你的路由链接组件渲染这些行:把收到的 props 展开传进去,并保留其中的 onClick,它负责选中这一行。

收起

collapsed 把菜单收窄到 collapsedWidth,只显示图标(没有图标的行显示标签的首字母)。每一行用 tooltip 显示名称,子菜单的内容在菜单旁边的浮层里打开。

手风琴

开启 accordion 后,展开一个子菜单会收起它旁边已展开的子菜单。

受控展开

expandedKeys 和 onUpdateExpandedKeys 控制哪些子菜单展开。

缩进

rootIndent 是第一层的起始内边距,indent 是每深一层增加的缩进。默认缩进等于图标宽度加间距,这样子项的标签和父项的标签对齐。

附加内容和禁用

extra 在行尾放附加内容,比如计数。disabled 的行不能聚焦,也不能选择。

无障碍

菜单采用 disclosure 导航模式,而不是 role="menu":menu 系列角色用于命令型的应用菜单,会让读屏软件进入另一种交互模式,链接和 Tab 的行为都会改变。这里每一行都是 Tab 顺序里的普通链接或按钮;子菜单是带 aria-expanded 和 aria-controls 的按钮;分组是由标题命名的列表;选中行带 aria-current(链接上是 page,按钮上是 true)。

键盘

Tab 在各行之间移动。Enter(按钮上也可以用 Space)选择一行或展开子菜单。另外,↑ / ↓ 在可见的行之间移动,Home / End 跳到首尾,→ 展开子菜单或进入已展开的子菜单,← 收起子菜单或回到当前行所在的子菜单。

Props

名称类型默认值说明版本
optionsMenuMixedOption[]必填行、子菜单、分组和分割线,见下文。未发布
value / defaultValueMenuKey | nullundefined / null受控 / 初始的选中 key。未发布
onUpdateValue(key, option) => voidundefined选择没有子项的行时调用。未发布
expandedKeys / defaultExpandedKeysMenuKey[]undefined受控 / 初始展开的子菜单。默认展开选中行的祖先。未发布
defaultExpandAllbooleanfalse初始展开全部子菜单。未发布
onUpdateExpandedKeys(keys: MenuKey[]) => voidundefined子菜单展开或收起时调用。未发布
accordionbooleanfalse展开子菜单时收起它已展开的兄弟子菜单。未发布
indent / rootIndentnumber主题每层的缩进 / 第一层的起始内边距(px)。未发布
collapsedbooleanfalse只显示图标;标签放进 tooltip,子菜单在浮层中打开。未发布
collapsedWidthnumber主题(48 / 52)收起时的宽度(px)。未发布
iconSize / collapsedIconSizenumber主题展开 / 收起时的图标大小(px)。未发布
disabledbooleanfalse禁用所有行。未发布
renderLabel(option) => ReactNodeundefined替换行和分组标题的标签。未发布
renderLink(props: MenuLinkProps, option) => ReactNodeundefined渲染带 href 的行,默认渲染 <a>。未发布

其余 props 和 ref 传给 <nav>。

名称类型说明
keystring | number必填且唯一。
labelReactNode行的文字。
iconReactNode在标签前面;收起时单独显示。
extraReactNode在行尾。
hrefstring让这一行成为链接。子菜单上无效。
disabledboolean不能选择或展开。
showboolean为 false 时不渲染该选项。
childrenMenuMixedOption[]让这一行成为子菜单。

分组是 { type: "group", key, label, children },分割线是 { type: "divider", key }。

说明

  • 目前只有 mode="vertical",横向的顶栏会单独规划。
  • 标签、图标和附加内容都是 ReactNode。链接用 href + renderLink,不要把路由链接塞进标签,这样整行都是链接。
  • 分组里的行和分组标题处在同一缩进,和大多数文档站侧边栏一致。
  • accordion 对每一层都生效。