Menu 菜单
独立的菜单列表,支持选中态与键盘导航。
基础用法
基础用法
默认选中
默认选中(value 回显)
禁用项
禁用项
多级子菜单
带 children 的菜单项显示展开箭头(›),点击或悬停展开子菜单,子菜单缩进展示;键盘 ArrowRight 进入、ArrowLeft 返回。
多级子菜单
水平导航
mode="horizontal" 时菜单项横排,呈顶部导航条样式;一级子菜单向下浮出,二级及以上仍向右浮出。
水平导航(顶部导航条样式)
收起态
collapsed(vertical / inline 生效,horizontal 不适用)将菜单收窄为只显示图标;vertical 模式悬停或点击图标项时子菜单向右浮出(子菜单内仍为完整菜单),inline 模式不浮出——子菜单仍就地展开(点击展开,悬停不展开)。
收起态(只显示图标)
分组
type: "group" 的菜单项渲染为带组标题的分区(组标题小字、次要色、不可点),组内子项平铺在同一层,可继续混入子菜单与分隔线。
分组
带图标
icon 使用 @oas-ui/icons 的图标名(内置图标名),以内联 SVG 渲染在文字左侧。
带图标
图标颜色(iconColor)
iconColor 字段显式固定图标颜色(优先于选中/禁用态默认色),支持任意 CSS 色值或 token;缺省 currentColor 随文字色。子元素声明式通道用 icon-color 属性。
图标颜色(iconColor / icon-color)
分隔线
type: "divider" 渲染一条细分隔线,不可点、不参与键盘导航。
分隔线
子元素声明式通道
除 items JSON 外,可用 <oas-menu-item> / <oas-menu-group> / <oas-menu-divider> 子元素声明式书写(items 属性显式设置时优先,未设置时解析子元素收敛到同一渲染路径)。默认插槽文本为 label,属性对齐 items 字段:value / disabled / loading / icon / kind / danger / href / target / rel;<oas-menu-item> 内直接嵌套子元素即递归为子菜单,<oas-menu-group> 的 label 属性为组标题(value 可作 radio 组 id),组内子元素平铺同层。子元素增删、属性与文本变化会自动重渲染(MutationObserver)。
子元素声明式(分组 / 分隔线 / 嵌套 / checkbox / danger / href)
动态增删(MutationObserver 自动刷新)
前置媒体(slot="leading")
菜单项支持前置媒体插槽:在 <oas-menu-item> 内放 <template slot="leading"> 或带 slot="leading" 的直接子元素,内容渲染在 label 前、优先于 icon 图标(同时给时 icon 不渲染);loading 加载态时 spinner 替换前置媒体位,收起态(collapsed)下媒体位与图标一致收敛(保留可见、间距归零——隐藏会让条目成为可 hover 的空白块)。适合头像、色块等任意富前置内容(items JSON 通道不支持——仅子元素声明式通道可用)。
头像前置媒体(avatar 例)
暗色菜单
theme="dark" 使菜单局部使用暗色 token(深背景 + 浅文字),独立于全局主题;不设置时跟随全局主题。
暗色菜单
选择事件
选择事件
多选(checkbox)
kind: "checkbox" 的叶子项渲染为方块勾选框(role="menuitemcheckbox",与 radio 的 ✓ 区分);多选勾选集以 JSON 数组形态写入 value,点击某项后 oas-select 的 detail 携带 checked(本次点击后的勾选态)。
多选(checkbox)
危险操作项
danger: true 使用红色语义(--oas-color-danger),用于删除、退出登录等危险操作;hover / 键盘高亮时红底加深。
危险操作项(danger)
链接项(href)
href 使菜单项渲染为 <a>(锚点语义:支持中键 / 右键新窗口,SEO 友好),target / rel 原样透传;点击仍会派发 oas-select 并写入选中态。示例链接用 target="_blank" 新开标签页,避免离开文档页。
链接项(href)
长菜单滚动
max-height 限定菜单可视高度(纯数字自动补 px),超出部分在菜单内部滚动,适合长列表。
长菜单滚动(max-height)
字符定位(typeahead)
菜单聚焦后直接输入字符,即跳转到 label 匹配的项(连续字符缓冲,500ms 无输入自动重置;前缀匹配优先,无前缀则包含匹配)。示例标签带英文便于按键触发:按 c 跳到 Copy,继续按 u(组合 cu)跳到 Cut。
字符定位(typeahead)
inline 侧边导航
mode="inline" 时子菜单就地展开(不浮出),是侧边导航的主流形态;展开 / 收起带高度过渡动画,支持多级嵌套。
inline 就地展开
受控展开
expanded(JSON 数组)为受控属性:外部设置 / 更新它即可指定展开的子菜单集合;每次展开 / 收起派发 oas-expand-change(detail: { expanded, value, isExpanded }),受控场景下宿主据此把状态写回 expanded。
expanded 受控展开
选中不收起
浮出形态(vertical / horizontal)默认选中叶子项即收起展开的子菜单(展开态是临时的);close-on-select="false" 可保持展开,适合在浮层里连续选多项。mode="inline" 侧边导航默认不收(用户需看到所在分区),close-on-select="true" 可改为收起。kind="checkbox" 项的勾选切换永不收起。close-on-select 为布尔属性:存在即真(含 close-on-select="" 空值),仅显式 "false" 关闭——未设置时才按上述形态缺省(inline 不收 / 浮出收)。
选中不收起(close-on-select)
vertical + close-on-select="false":点叶子后子菜单保持展开
inline + close-on-select="true":点叶子后收起父级子菜单
手风琴
accordion(配合 mode="inline")使同级子菜单互斥:展开一个自动收起同级的其他展开项。
手风琴互斥(inline + accordion)
水平溢出收纳
mode="horizontal" 下容器宽度不足时,超宽的菜单项自动收进末尾「···」子菜单,导航条不换行、不截断。
水平溢出收纳
悬停展开子菜单
open-on-hover 让 vertical / inline 模式的父项支持 hover 展开:悬停约 150ms 后展开、移出约 300ms 后收起(宽限期内移回取消收起);点击路径不变(仍可点击展开/收起)。mode="horizontal" 顶部导航与 collapsed 收起态的 flyout 本就是即时 hover 浮出,不受该属性影响。
open-on-hover(vertical 悬停延迟展开)
vertical:悬停「编辑」~150ms 展开,移出~300ms 收起
inline:悬停同样延迟展开(多开并存),点击仍可切换
整单禁用
disabled 禁用整个菜单:点击 / 悬停 / 键盘全部拦截(href 项同时阻断原生跳转),宿主文字走禁用色(不叠 opacity)并同步 aria-disabled;移除属性即恢复交互。
整单禁用
纯动作菜单(selectable=false)
selectable="false" 关闭整单选中态语义:全部叶子项按动作项渲染(menuitem、无勾选标记、无 aria-checked),点击只派发 oas-select、不写回 value——适合「点了就走」的纯命令菜单(等价于把每个叶子项写成 kind: "action")。
纯动作菜单(无勾选态,不写回 value)
尚未点击
选中不收起(persistent)
persistent 让选中后浮出子菜单不自动收起(close-on-select 族的正向开关,显式时优先于 close-on-select):适合需要连续选择、选中后停留在当前位置的场景;value 照常写回。
persistent:选中后子菜单保持展开
悬停父项展开子菜单后点击试试
可搜索(searchable)
searchable 在菜单顶部渲染过滤输入框,键入实时过滤可见项(浮出与 inline 形态都生效):命中嵌套子项时保留其祖先并自动展开命中路径,无匹配时显示空文案(复用 i18n 空态);Escape 清空搜索,ArrowDown 把焦点移入菜单。
可搜索(浮出 + inline)
浮出形态:在输入框键入「窗」过滤出「窗口布局」
inline 形态:键入「统计」就地过滤并展开命中路径
快捷键标注(shortcut)
菜单项 shortcut 字段(items JSON)或 <oas-menu-item shortcut="…"> 属性在行右端渲染 kbd 快捷键标注,与 menubar 的 shortcut 视觉契约一致。
快捷键标注(shortcut)
API
oas-menu
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
accordion | 手风琴互斥(inline 模式同级只展开一个子菜单) | boolean | — |
close-on-select | 选中叶子项后是否收起展开的子菜单。缺省分形态:inline 侧边导航不收、浮出形态收;checkbox 项勾选切换永不收起 | string | — |
collapsed | 收起态(vertical / inline 生效,horizontal 不适用):只显示图标,子菜单向右浮出 | boolean | — |
disabled | 整单禁用:点击/悬停/键盘全拦截,降饱和 + aria-disabled | boolean | — |
expanded | 受控展开项集合(JSON 数组字符串,inline 模式哪些子菜单展开);非受控时内部管理 | string | — |
items | 菜单项 JSON(支持 disabled / loading 禁点、icon、children 子菜单) | MenuItem[] | null | [] |
max-height | 长菜单最大高度,超出内部滚动(数字补 px) | string | — |
mode | 布局模式:vertical(默认)纵向菜单 / horizontal 顶部导航条 / inline 侧边导航(子菜单就地展开、带高度过渡) | — | — |
open-on-hover | vertical/inline 父项 hover 延迟展开(约 150ms)/移出延迟收起(约 300ms),点击路径不变;horizontal 与 collapsed flyout 不受影响 | boolean | — |
persistent | 选中后不自动收起浮出子菜单(优先于 close-on-select) | string | — |
searchable | 菜单顶部过滤输入框:键入实时过滤可见项(命中嵌套子项保留祖先并自动展开,Esc 清空) | boolean | — |
selectable | "false" 时纯动作菜单:叶子无勾选态、点击不写回 value(detail kind=action) | string | true |
theme | 局部主题:dark 使用暗色 token(独立于全局主题) | — | — |
value | 当前选中值。纯字符串时全局单选(无组场景,兼容旧用法);JSON 对象字符串(如 {"sort":"name","view":"list"})时按组 id 作用域独立记录——type:"group" 项的 value 作组 id,组内点选只更新该组 | string | — |
事件
| 事件 | 说明 |
|---|---|
oas-expand-change | 子菜单展开状态变化,detail: { expanded: string[], value, isExpanded }(受控/非受控都派发) |
oas-select | 选择某项,detail: { value, kind? }。kind 仅动作项(kind: "action")出现,值为 "action";radio 项 detail.kind 不出现 |
CSS 变量
| CSS 变量 | 默认值 |
|---|---|
--oas-menu-max-height | none |
oas-menu-item
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
danger | 破坏性项:红色语义(删除/退出等危险操作) | — | — |
disabled | 禁用该项 | — | — |
href | 链接地址:有 href 时渲染为原生 <a>(真实跳转 + 照常派发 oas-select) | — | — |
icon | 前置图标(@oas-ui/icons 内置图标名) | — | — |
icon-color | 图标颜色:显式固定该色(优先于选中/禁用态默认色);缺省 currentColor 随文字色 | — | — |
kind | 叶子项语义:radio(默认,可勾选)/ action(动作项,无勾选态、不写回 value)/ checkbox(多选勾选,value 数组勾选集) | — | — |
loading | 加载中:渲染 spinner、禁点,由数据驱动恢复 | — | — |
rel | 链接 rel(配合 href) | — | — |
shortcut | 行右端快捷键标注(kbd 视觉,对齐 menubar shortcut 契约) | — | — |
target | 链接 target(配合 href) | — | — |
value | 选中值(子元素声明式通道的数据载体字段) | — | — |
插槽
| 名称 | 说明 |
|---|---|
| 默认 | 菜单项 label 内容(默认插槽文本);直接子元素 <oas-menu-item>/<oas-menu-group>/<oas-menu-divider> 递归为子菜单 children |
template[slot="leading"] | 前置媒体模板(或直接子元素加 slot="leading"):头像/色块等任意前置内容,渲染在 label 前、优先于 icon 图标;loading 态由 spinner 替换;仅子元素声明式通道可用(items JSON 不支持) |
oas-menu-group
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
label | 分组标题(组标题小字、次要色、不可点) | — | — |
value | radio 组 id(组内点选只更新该组选中值) | — | — |
插槽
| 名称 | 说明 |
|---|---|
| 默认 | 组内菜单项:子元素 <oas-menu-item>/<oas-menu-group>/<oas-menu-divider> 平铺同层 |
oas-menu-divider
插槽
| 名称 | 说明 |
|---|---|
| 默认 | 分隔线数据载体(无属性,宿主解析为 type: "divider") |
MenuItem 字段:
| 字段 | 说明 | 类型 |
|---|---|---|
label | 菜单项文字 | string |
value | 选中值 | string |
type | 菜单项类型:item(默认)/ group(分组标题)/ divider(分隔线) | string |
kind | 叶子项语义:radio(默认,可勾选)/ action(动作项,无勾选态、点击不写回 value) | string |
icon | 图标名(registerIcon() 自定义或 @oas-ui/icons 内置图标名) | string |
iconColor | 图标颜色(可选):显式固定该色,优先于选中/禁用态默认色;缺省 currentColor 随文字色 | string |
disabled | 禁用该项 | boolean |
children | 子菜单项数组,结构与父项一致(可继续嵌套) | MenuItem[] |
children 为可选子菜单项数组;有 children 的项点击/悬停展开子菜单,选中态只落在叶子项。group 的 children 平铺展示在同一层,组标题不可点、不参与键盘导航;divider 不可点、不参与键盘导航。
键盘导航:方向键移动(自动跳过组标题与分隔线)、Enter 选择(含子菜单的项 Enter/ArrowRight 进入)、Home / End 跳转、ArrowLeft 返回父级;role="menu" + menuitemradio(子菜单父项为 menuitem),选中项显示对勾。