Menu 菜单DropdownMenu · Menu
点击一个按钮,弹出一列操作让用户挑一个执行。DropdownMenu 是带触发按钮的完整下拉菜单;右键触发见 ContextMenu;要从选项里选一个“值”而不是执行操作,用 Select。
下拉菜单
trigger 通常是 Button。菜单项可以带图标、快捷键提示(只是文字,不负责绑定按键)和禁用状态。点选后默认收起整个菜单。
上一次操作:还没有操作
状态色项
tone 给菜单项上状态色:文字和图标用状态色,高亮换成同色的柔和底。危险操作(删除、退出)用 danger,并且放在最后、用分隔线隔开。
复选项、单选项与受控
MenuCheckboxItem 和 MenuRadioItem 点选后默认不收起菜单,方便连续调整。MenuLabel 是分组小标题。DropdownMenu 的开关用 open / onOpenChange 受控。
菜单已关闭 · 网格线开 · 隐藏文件关 · 排序 updated
子菜单
MenuSub 的 label 是触发项上的文字,children 是子菜单里的项。悬停、点击或按 → 展开,← 或 Esc 收回。子菜单尽量只用一层。
位置与宽度
默认在触发按钮下方、左对齐,并且不窄于触发按钮。
单独使用 Menu
Menu 是 role="menu" 的列表本体,可以不带触发按钮直接放在页面里(比如放进你自己的浮层)。此时没有“收起”的概念,点选只触发 onSelect。
规格
- 进场
- 淡入 + 下移 6px · 150ms ease-out,不缩放
- 高亮块
- 90ms ease-out · 紧跟指针,不回弹
- 状态项
- 成功 / 警告 / 危险:文字和图标用状态色,高亮换成同色柔和底
- 选中
- 中性色对勾,描线画出
- 退场
- 90ms ease-in
API
DropdownMenu
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
trigger* | ReactElement | — | 触发元素:要能接收 ref 和事件。 |
children* | ReactNode | — | 菜单项。 |
open / defaultOpen | boolean | false | 是否打开(受控 / 非受控)。 |
onOpenChange | (open: boolean) => void | — | 开关状态变化时触发。 |
placement | Placement | 'bottom-start' | 相对触发元素的位置。 |
offset | number | 8 | 与触发元素的间距(px)。 |
matchTriggerWidth | boolean | true | 菜单不窄于触发元素。 |
MenuItem
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
icon | IconName | ReactNode | — | 前置图标。 |
shortcut | ReactNode | — | 右侧的快捷键提示,只是文字。 |
tone | 'neutral' | 'success' | 'warning' | 'danger' | 'info' | 'neutral' | 状态色。 |
disabled | boolean | — | 禁用:方向键会跳过,点击无效。 |
onSelect | () => void | — | 被点选或用 Enter / Space 触发。 |
closeOnSelect | boolean | true(勾选 / 单选项为 false) | 触发后是否收起整个菜单。 |
textValue | string | — | 首字母跳转用的文字;默认取项里的文字内容。 |
MenuCheckboxItem / MenuRadioGroup / MenuRadioItem / MenuSub
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
MenuCheckboxItem · checked / defaultChecked | boolean | — | 是否勾选(受控 / 非受控)。 |
MenuCheckboxItem · onCheckedChange | (checked: boolean) => void | — | 勾选状态变化时触发。 |
MenuRadioGroup · value / defaultValue | string | null | — | 选中项(受控 / 非受控)。 |
MenuRadioGroup · onChange | (value: string) => void | — | 选中项变化时触发。 |
MenuRadioItem · value* | string | — | 这一项的值,必须放在 MenuRadioGroup 里。 |
MenuSub · label* | ReactNode | — | 触发项上的文字。 |
MenuSub · children* | ReactNode | — | 子菜单里的项。 |
MenuSub · icon / tone / disabled | — | — | 同 MenuItem。 |
Menu
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
focusOnOpen | 'first' | 'last' | 'menu' | null | — | 挂载时把焦点放到哪;null 表示不动焦点。 |
bare | boolean | — | 不带浮层表面(放在自己的浮层里时用)。 |
无障碍
- 触发按钮带
aria-haspopup="menu"和aria-expanded;菜单是role="menu",各项是menuitem/menuitemcheckbox/menuitemradio,分隔线是separator。 - 在触发按钮上:Enter / Space / ↓ 打开并聚焦第一项,↑ 打开并聚焦最后一项。鼠标点开时焦点在菜单本身,不预先高亮任何项。
- 在菜单里:↑ ↓ 移动(循环),Home / End 到两端,Enter / Space 触发,打字母跳到以它开头的项。
- 子菜单:→ 展开并进入,← 或 Esc 收回到父项。
- Esc 关闭并把焦点还给触发按钮;Tab 关闭菜单并移到触发按钮之后的下一个元素。
- 禁用项是
aria-disabled,方向键会跳过。状态色项除了颜色还应该有图标或明确的文字。