跳转到内容

右键菜单 context-menu

导航组件。三层同源:无头内核给出解剖与状态机,Vue 组件与自定义元素只是它的两层外壳,行为完全一致。

示例

基础用法

collection 是条目的事实源,结构由组件铺开;在触发区上右键(触摸端长按),菜单钉在按下去的那一点上

在这块区域上右键
最近选中:(无)

分组与标记位

group 用 value 跟自己的 group-label 配对,item-indicator 是纯装饰的勾选位

右键看看排序与视图两组
当前排序:按名称

受控与锚点

传了 open 就由宿主说了算;root 的插槽给出锚点坐标与 openAt,可以从任意位置弹出

右键这里,或者用下面的按钮从固定坐标弹出
已收起

语气

tone 决定条目高亮与标记位用哪族颜色;高亮静止态看不出来,右键弹出后悬停条目、或用方向键把焦点移上去才显现

brand
neutral
success
warning
danger
info

尺寸

size 换的是条目的内边距、间距与字号;三档各挂一块触发区,逐块右键对比

sm
缺省
lg

放置位与箭头

placement 是相对光标那一点的首选位,offset 把浮层从光标推开;arrow 指回那一点

在这块区域上右键:菜单落在光标右侧,箭头指回光标

条目里的图标与快捷键

item-text 只是文字那一段,图标与快捷键提示作为兄弟节点排在它两侧

右键看带图标与快捷键的条目

触发与连打

longPressDelay 是触摸端按住多久算触发;typeahead 决定展开后的可打印字符是拿去检索还是放行给页面

触摸端按住 300ms 即弹出;展开后敲 E 跳到 Excel 那一条
连打检索关掉:展开后敲 E 焦点不动

产物

自定义元素<xh-context-menu>
Vue 组件XhContextMenuArrow XhContextMenuContent XhContextMenuGroup XhContextMenuGroupLabel XhContextMenuItem XhContextMenuItemIndicator XhContextMenuItemText XhContextMenuPositioner XhContextMenuRoot XhContextMenuSeparator XhContextMenuTrigger
组合式函数useContextMenu
状态机contextMenuMachine
皮肤@xihan-ui/styles/context-menu.css

解剖

部件名即 data-part 属性值,也是皮肤的选择器。加粗的是必备部件,不渲染它组件不工作(Web Components 适配器会在诊断通道上报 wc.missing-part)。

data-scope="context-menu"root · trigger · positioner · content · item · item-text · item-indicator · separator · group · group-label · arrow

Props

属性类型必填说明
collectionContextMenuNode[]条目数据,显示文本、禁用、标记位与分组的事实源。给了它,条目部件只需报 value。 缺省即回到「文本与禁用全写在条目部件上」的老路。
openboolean展开态。给定即受控:内部不再自改,只发 onOpenChange。
defaultOpenboolean
placementPlacement相对光标那一点的首选放置位,默认 bottom-start。
offsetnumber浮层与光标的间距(px),默认 0——右键菜单要贴着光标。
loopboolean方向键走到尽头是否回绕,默认 true。
dirDirection文字方向,默认 ltr。
typeaheadboolean连打检索,默认开。关掉后可打印字符一律放行给页面。
longPressDelaynumber触摸端长按多久算触发(ms),默认 700。
toneTone语气:brand / neutral / success / warning / danger / info,决定条目高亮与标记位用哪族颜色。
sizeSize尺寸:sm / md / lg,决定条目高度、内边距与字号档位。
onOpenChange(details: ContextMenuOpenChangeDetails) => voidopen 变化意图回调;受控时是唯一出口,非受控时随内部转移一并通知。
onSelect(details: ContextMenuSelectDetails) => void条目被选中;菜单随之关闭。

状态机

状态closed · pressing · open

事件CONTEXT.MENU · OPEN · CLOSE · PRESS.START · PRESS.MOVE · PRESS.END · after.longPressDelay · CONTROLLED.OPEN · CONTROLLED.CLOSE · ITEM.FOCUS · ITEM.LOST · ITEM.SELECT

判据isOpenControlled · movedBeyondTolerance

connect API

useContextMenu 产出的对象。getXxxProps() 铺到对应部件的宿主元素上,其余是可读状态与操作入口。

成员类型说明
openboolean
collectionreadonly ContextMenuNodeMeta[]collection 推出的条目元信息,按数据顺序排列;没给 collection 即空数组。
pressingboolean长按计时进行中;触发区据此给按压反馈。
pointContextMenuPoint | null当前锚点坐标;一次都没打开过时为 null。
focusedValuestring | null焦点锚点;收起时为 null。
setOpen(next: boolean) => void收起走 CLOSE;展开落在最近一次锚点坐标上(从未打开过则是原点)。
openAt(x: number, y: number) => void命令式展开到指定视口坐标。
getRootProps() => T['element']
getTriggerProps() => T['element']
getPositionerProps() => T['element']
getContentProps() => T['element']
getItemProps(props: ContextMenuItemProps) => T['element']
getItemTextProps(props: ContextMenuItemProps) => T['element']
getItemIndicatorProps(props: ContextMenuItemProps) => T['element']
getSeparatorProps() => T['element']
getGroupProps(props: ContextMenuGroupProps) => T['element']
getGroupLabelProps(props: ContextMenuGroupProps) => T['element']
getArrowProps() => T['element']

键盘

规格出处:W3C APG

按键生效条件行为
ContextMenu / Shift+F10focus in trigger在触发区起始角展开菜单并把焦点落到首个可用条目
ArrowDownopen, focus in content焦点移到下一个条目(禁用项跳过、尽头按 loop 回绕)
ArrowUpopen, focus in content焦点移到上一个条目(禁用项跳过、尽头按 loop 回绕)
Homeopen, focus in content焦点移到首个可用条目
Endopen, focus in content焦点移到末个可用条目
单个可打印字符open, typeahead 未关连打检索把焦点移到首字母匹配的条目,不选中它
Enter / Spacefocus in item, not disabled派发选中详情并关闭菜单,焦点归还触发区
Escapeopen关闭菜单并把焦点归还触发区
Tab / Shift+Tabopen关闭菜单,焦点不归还触发区,按 Tab 序列自然离开

Released under The MIT License