跳到正文
GitHub

浮层

SearchableMenu

一个能打字筛选的动作菜单。

什么时候用它

DropdownMenu 超过十几行就不再能扫读,而用二级菜单去救只会更糟。这就是同一份列表加上一个过滤框。它不是 Command 面板:那个是页面级的、模态的;这个锚在某个控件上。

示例

default

nine actions, one filter

说明

一个能打字筛选的动作菜单。

这个正方形本来只有三个角,它是第四个;值得把区别讲清楚,因为拿错太容易了:

| | 选项少 | 选项多 | |---|---|---| | 设置一个值 | Select | Combobox | | 执行一个动作 | DropdownMenu | SearchableMenu |

DropdownMenu 超过十几行就不再能扫读,而通常的应对——套二级菜单——只会更糟。这个就是同一份列表,上面加一个筛选框。

Command 不是一回事:那个是页面级的面板,通常是模态的,通常绑在 ⌘K 上。这个锚在某个控件上,就像它替代的那个菜单一样。

这些行是 listbox 里的 option 而不是 menuitem,因为筛选这个模式要求如此——高亮通过 aria-activedescendant 移动而焦点留在输入框里,菜单做不到这件事。这个取舍是刻意的:一个没法筛的菜单,对读者来说比一个会执行动作的 listbox 更糟。

属性

SearchableMenu props
属性类型默认值说明
actions必填MenuAction[]
children必填ReactNode触发器上的文字。
label必填string给这个菜单起名字,供辅助技术使用。
align'start' | 'center' | 'end''start'
classNamestring
emptyMessagestring'Nothing matches.'
searchPlaceholderstring'Filter…'

键盘操作

SearchableMenu keyboard interactions
按键作用
EnterSpace打开菜单。
移动高亮,焦点始终留在筛选框里。
Enter执行高亮那一项动作。
Escape什么都不执行,直接关闭。

无障碍

  • 在有边界的框里——设备预览、内嵌控制台——用 `<OverlayContainer container={el}>` 包住这棵子树。面板会渲染进那个元素,按它的边界翻转,而不是按视口;框上设的 `dir` 和 `data-density` 也就跟着生效了。
  • 行是 listbox 里的 option 而不是 menuitem,因为过滤这件事要求如此——高亮通过 aria-activedescendant 移动,焦点留在输入框里,而菜单做不到。
  • 这个取舍是刻意的:一个没法筛的菜单,对读者来说比一个会执行动作的 listbox 更糟。