集成菜单 UI 组件
一个基于 Ariakit 构建的强大菜单组件,提供层级导航、搜索功能、筛选能力和完全的键盘无障碍支持。非常适合命令面板、下拉菜单及复杂的导航系统。
安装
你可以通过 Tiptap CLI 添加该原语组件
npx @tiptap/cli@latest add menu使用示例
import {
Menu,
MenuContent,
MenuItem,
MenuGroup,
MenuGroupLabel,
MenuButton,
MenuButtonArrow,
useComboboxValueState,
} from '@/components/tiptap-ui-primitive/menu'
import { Button } from '@/components/tiptap-ui-primitive/button'
import { ComboboxList } from '@/components/tiptap-ui-primitive/combobox'
export default function MyComponent() {
const [searchValue] = useComboboxValueState()
return (
<Menu trigger={<Button>打开菜单</Button>}>
<MenuContent>
<ComboboxList>
<MenuGroup>
<MenuGroupLabel>操作</MenuGroupLabel>
<MenuItem
onClick={() => console.log('剪切')}
render={<Button data-style="ghost">剪切</Button>}
/>
<MenuItem
onClick={() => console.log('复制')}
render={<Button data-style="ghost">复制</Button>}
/>
<MenuItem
onClick={() => console.log('粘贴')}
render={<Button data-style="ghost">粘贴</Button>}
/>
</MenuGroup>
</ComboboxList>
</MenuContent>
</Menu>
)
}组件
Menu
根菜单提供者,负责状态管理和上下文。
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| trigger | React.ReactNode | - | 触发菜单显示的元素 |
| value | string | - | 当前搜索值(用于可搜索菜单) |
| onOpenChange | (open: boolean) => void | - | 菜单开关状态变化的回调 |
| onValueChange | (value: string) => void | - | 搜索值变化的回调 |
| onValuesChange | (values: string[]) => void | - | 多选时的回调 |
| open | boolean | - | 控制菜单的打开状态 |
MenuContent
菜单项的容器,负责定位和样式。
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| onClickOutside | (event: MouseEvent | TouchEvent | FocusEvent) => void | - | 点击菜单外部时的回调 |
MenuItem
单个可选的菜单项。
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| group | string | - | 菜单项所属组标识 |
| name | string | - | 菜单项名称标识 |
| parentGroup | string | - | 父级组标识 |
| preventClose | boolean | false | 选中时是否阻止菜单关闭 |
| render | React.ReactElement | - | 自定义渲染元素 |
钩子
useComboboxValueState
用于访问和更新可搜索菜单中的搜索值的钩子。
const [searchValue, setSearchValue] = useComboboxValueState()返回值: readonly [string, (value: string) => void]
useMenuPlacement
获取当前菜单定位侧的钩子。
const side = useMenuPlacement()返回值: string - 当前侧("top", "bottom", "left", "right")
useMenuItemClick
用于处理菜单项点击并可选阻止菜单关闭的钩子。
const handleClick = useMenuItemClick(menu, preventClose)参数:
menu?: Ariakit.MenuStore- 菜单状态实例preventClose?: boolean- 是否阻止菜单关闭
筛选与搜索
Menu 组件包含强大的筛选功能:
filterMenuItems
基于搜索条件筛选菜单项的工具函数。
import { filterMenuItems } from '@/components/tiptap-ui-primitive/menu'
const filteredItems = filterMenuItems({ items: menuItems, label: '操作' }, searchValue)filterMenuGroups
用于筛选整个菜单组的工具函数。
import { filterMenuGroups } from '@/components/tiptap-ui-primitive/menu'
const filteredGroups = filterMenuGroups(menuGroups, searchValue)依赖
- @ariakit/react - 无障碍和交互原语
- combobox - 搜索功能
- separator - 分组视觉分隔
- label - 分组标签
- use-on-click-outside - 外部点击检测
- use-composed-ref - 引用组合工具