<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuItemIndicator,
ContextMenuLabel,
ContextMenuPortal,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from 'reka-ui'
import { ref } from 'vue'
const checkboxOne = ref(false)
const checkboxTwo = ref(false)
const person = ref('pedro')
function handleClick() {
// eslint-disable-next-line no-alert
alert('hello!')
}
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger
as-child
class="block border-2 border-stone-700 dark:border-white border-dashed text-stone-700 dark:text-white rounded-xl text-sm select-none py-[45px] w-[300px] text-center"
>
<span> Right click here. </span>
</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent
class="min-w-[220px] z-30 bg-white outline-none rounded-md p-[5px] shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade"
:side-offset="5"
>
<ContextMenuItem
value="New Tab"
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
@click="handleClick"
>
New Tab <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+T
</div>
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger
value="more toolsz"
class="group w-full text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[state=open]:bg-green4 data-[state=open]:text-grass11 data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1 data-[highlighted]:data-[state=open]:bg-green9 data-[highlighted]:data-[state=open]:text-green1"
>
More Tools <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
<Icon icon="radix-icons:chevron-right" />
</div>
</ContextMenuSubTrigger>
<ContextMenuPortal>
<ContextMenuSubContent
class="min-w-[220px] z-30 outline-none bg-white rounded-md p-[5px] shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade"
:side-offset="2"
:align-offset="-5"
>
<ContextMenuItem
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Save Page As… <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+S
</div>
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Create Shortcut…
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Name Window…
</ContextMenuItem>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Developer Tools
</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuPortal>
</ContextMenuSub>
<ContextMenuItem
value="New Window"
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
New Window <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+N
</div>
</ContextMenuItem>
<ContextMenuItem
value="New Private Window"
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
disabled
>
New Private Window <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⇧+⌘+N
</div>
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger
value="more tools"
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none w-full outline-none data-[state=open]:bg-green4 data-[state=open]:text-grass11 data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1 data-[highlighted]:data-[state=open]:bg-green9 data-[highlighted]:data-[state=open]:text-green1"
>
More Tools <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
<Icon icon="radix-icons:chevron-right" />
</div>
</ContextMenuSubTrigger>
<ContextMenuPortal>
<ContextMenuSubContent
class="min-w-[220px] z-30 outline-none bg-white rounded-md p-[5px] shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade"
:side-offset="2"
:align-offset="-5"
>
<ContextMenuItem
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Save Page As… <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+S
</div>
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Create Shortcut…
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Name Window…
</ContextMenuItem>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Developer Tools
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger
value="more toolsz"
class="group w-full text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[state=open]:bg-green4 data-[state=open]:text-grass11 data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1 data-[highlighted]:data-[state=open]:bg-green9 data-[highlighted]:data-[state=open]:text-green1"
>
More Tools <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
<Icon icon="radix-icons:chevron-right" />
</div>
</ContextMenuSubTrigger>
<ContextMenuPortal>
<ContextMenuSubContent
class="min-w-[220px] z-30 outline-none bg-white rounded-md p-[5px] shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade"
:side-offset="2"
:align-offset="-5"
>
<ContextMenuItem
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Save Page As… <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+S
</div>
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Create Shortcut…
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Name Window…
</ContextMenuItem>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Developer Tools
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger
value="more toolsz"
class="group w-full text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[state=open]:bg-green4 data-[state=open]:text-grass11 data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1 data-[highlighted]:data-[state=open]:bg-green9 data-[highlighted]:data-[state=open]:text-green1"
>
More Tools <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
<Icon icon="radix-icons:chevron-right" />
</div>
</ContextMenuSubTrigger>
<ContextMenuPortal>
<ContextMenuSubContent
class="min-w-[220px] z-30 outline-none bg-white rounded-md p-[5px] shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade"
:side-offset="2"
:align-offset="-5"
>
<ContextMenuItem
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Save Page As… <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+S
</div>
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Create Shortcut…
</ContextMenuItem>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Name Window…
</ContextMenuItem>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Developer Tools
</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuPortal>
</ContextMenuSub>
</ContextMenuSubContent>
</ContextMenuPortal>
</ContextMenuSub>
<ContextMenuItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
Developer Tools
</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuPortal>
</ContextMenuSub>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuCheckboxItem
v-model="checkboxOne"
class="group text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
<ContextMenuItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator> Show Bookmarks <div
class="ml-auto pl-[20px] text-mauve11 group-data-[highlighted]:text-white group-data-[disabled]:text-mauve8"
>
⌘+B
</div>
</ContextMenuCheckboxItem>
<ContextMenuCheckboxItem
v-model="checkboxTwo"
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
>
<ContextMenuItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator> Show Full URLs
</ContextMenuCheckboxItem>
<ContextMenuSeparator class="h-[1px] bg-green6 m-[5px]" />
<ContextMenuLabel class="pl-[25px] text-xs leading-[25px] text-mauve11">
People
</ContextMenuLabel>
<ContextMenuRadioGroup v-model="person">
<ContextMenuRadioItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
value="pedro"
>
<ContextMenuItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:dot-filled" />
</ContextMenuItemIndicator> Pedro Duarte
</ContextMenuRadioItem>
<ContextMenuRadioItem
class="text-xs leading-none text-grass11 rounded-[3px] flex items-center h-[25px] px-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:bg-green9 data-[highlighted]:text-green1"
value="colm"
>
<ContextMenuItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:dot-filled" />
</ContextMenuItemIndicator> Colm Tuite
</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
功能特点
- 支持带可配置阅读方向的子菜单。
- 支持项目、标签、项目组。
- 支持可勾选项目(单选或多选),并可选不确定状态。
- 支持模态和非模态模式。
- 自定义侧边、对齐方式、偏移量、碰撞处理。
- 焦点完全管理。
- 完整的键盘导航。
- 类型提前支持(Typeahead support)。
- 关闭和分层行为高度可定制。
- 在触摸设备上通过长按触发。
安装
从命令行安装组件。
$ npm add reka-ui
$ pnpm add reka-ui
$ yarn add reka-ui
$ bun add reka-ui
结构
导入所有部分并将其组合在一起。
<script setup lang="ts">
import {
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuItemIndicator,
ContextMenuLabel,
ContextMenuPortal,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger />
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuLabel />
<ContextMenuItem />
<ContextMenuGroup>
<ContextMenuItem />
</ContextMenuGroup>
<ContextMenuCheckboxItem>
<ContextMenuItemIndicator />
</ContextMenuCheckboxItem>
<ContextMenuRadioGroup>
<ContextMenuRadioItem>
<ContextMenuItemIndicator />
</ContextMenuRadioItem>
</ContextMenuRadioGroup>
<ContextMenuSub>
<ContextMenuSubTrigger />
<ContextMenuPortal>
<ContextMenuSubContent />
</ContextMenuPortal>
</ContextMenuSub>
<ContextMenuSeparator />
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
API 参考
遵循 Menu WAI-ARIA 设计模式 并使用 漫游 tabindex 来管理菜单项之间的焦点移动。
Root
包含上下文菜单的所有部分。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
dir | 'ltr' | 'rtl' | 适用时,组合框的阅读方向。如果省略,则全局继承自 ConfigProvider 或假定为 LTR(从左到右)阅读模式。 | |
modal | true | boolean | 下拉菜单的模态。当设置为 true 时,与外部元素的交互将被禁用,并且只有菜单内容对屏幕阅读器可见。 |
触发事件 (Emit)
| 事件 | Payload | 描述 |
|---|---|---|
update:open | [payload: boolean] | 子菜单打开状态改变时调用的事件处理程序。 |
Trigger
打开上下文菜单的区域。将其包裹在您希望上下文菜单在右键单击(或使用相关键盘快捷键)时打开的目标周围。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'span' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | false | boolean | 当为 true 时,右键单击时不会打开上下文菜单。请注意,这也会恢复原生上下文菜单。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "open" | "closed" |
Portal
当使用时,将内容部分传送到 body 中。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
defer | boolean | 延迟 Teleport 目标的解析,直到应用程序的其他部分挂载(需要 Vue 3.5.0+)。 参考 | |
disabled | boolean | 禁用 Teleport 并内联渲染组件。 参考 | |
forceMount | boolean | 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 | |
to | string | HTMLElement | Vue 原生 Teleport 组件 prop :to。 参考 |
Content
在打开的上下文菜单中弹出的组件。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
alignFlip | boolean | 在与边界发生碰撞时翻转对齐方式。仅当 prioritizePosition 为 true 时才会发生。 | |
alignOffset | 0 | number | 从 start 或 end 对齐选项的像素偏移量。 |
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
avoidCollisions | true | boolean | 当为 true 时,覆盖侧边和对齐偏好以防止与边界边缘碰撞。 |
collisionBoundary | [] | Element | (Element | null)[] | null | 用作碰撞边界的元素。默认情况下是视口,但您可以提供额外的元素以包含在此检查中。 |
collisionPadding | 0 | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>> | 碰撞检测应发生的边界边缘的像素距离。接受一个数字(所有边相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。 |
disableUpdateOnLayoutShift | boolean | 是否在布局偏移时禁用内容更新位置。 | |
forceMount | boolean | 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 | |
hideWhenDetached | false | boolean | 当触发器完全被遮挡时是否隐藏内容。 |
loop | boolean | 当为 true 时,键盘导航将从最后一个项目循环到第一个,反之亦然。 | |
positionStrategy | 'fixed' | 'absolute' | 要使用的 CSS position 属性类型。 | |
prioritizePosition | boolean | 强制内容在视口内定位。可能会与参考元素重叠,这可能不是期望的。 | |
reference | ReferenceElement | 将作为浮动元素定位参考的自定义元素或虚拟元素。如果提供,它将替换默认锚点元素。 | |
sticky | 'partial' | 'partial' | 'always' | 对齐轴上的粘性行为。partial 将使内容保持在边界内,只要触发器至少部分在边界内,而 always 将无论如何都使内容保持在边界内。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
closeAutoFocus | [event: Event] | 关闭时自动聚焦时调用的事件处理程序。可以阻止。 |
escapeKeyDown | [event: KeyboardEvent] | Escape 键按下时调用的事件处理程序。可以阻止。 |
focusOutside | [event: FocusOutsideEvent] | 焦点移出 DismissableLayer 时调用的事件处理程序。可以阻止。 |
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent] | 当 DismissableLayer 外部发生交互时调用的事件处理程序。具体来说,当 pointerdown 事件发生在外部或焦点移出时。可以阻止。 |
pointerDownOutside | [event: PointerDownOutsideEvent] | 当 pointerdown 事件发生在 DismissableLayer 外部时调用的事件处理程序。可以阻止。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS 变量
| 变量 | 描述 |
|---|---|
--reka-context-menu-content-transform-origin | 从内容和箭头位置/偏移量计算的 transform-origin |
--reka-context-menu-content-available-width | 触发器和边界边缘之间剩余的宽度 |
--reka-context-menu-content-available-height | 触发器和边界边缘之间剩余的高度 |
--reka-context-menu-trigger-width | 触发器的宽度 |
--reka-context-menu-trigger-height | 触发器的高度 |
Arrow
一个可选的箭头元素,与子菜单一起渲染。这可以用于帮助将触发项目与 ContextMenu.Content 视觉链接起来。必须在 ContextMenu.Content 内部渲染。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'svg' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
height | 5 | number | 箭头的像素高度。 |
rounded | boolean | 当为 true 时,渲染圆角版本的箭头。不适用于 as/asChild。 | |
width | 10 | number | 箭头的像素宽度。 |
Item
包含上下文菜单项目的组件。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | boolean | 当为 true 时,阻止用户与项目交互。 | |
textValue | string | 用于类型提前的可选文本。默认情况下,类型提前行为将使用项目的 .textContent。当内容复杂或内部有非文本内容时使用。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
select | [event: Event] | 当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。 |
数据属性
| 属性 | 值 |
|---|---|
[data-highlighted] | 高亮时存在 |
[data-disabled] | 禁用时存在 |
Group
用于分组多个 ContextMenu.Items。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
Label
用于渲染标签。它不能使用箭头键聚焦。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
CheckboxItem
可以像复选框一样控制和渲染的项目。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | boolean | 当为 true 时,阻止用户与项目交互。 | |
modelValue | false | true | 'indeterminate' | 受控的勾选状态。可以作为 v-model 使用。 | |
textValue | string | 用于类型提前的可选文本。默认情况下,类型提前行为将使用项目的 .textContent。当内容复杂或内部有非文本内容时使用。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
select | [event: Event] | 当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。 |
update:modelValue | [payload: boolean] | 当值改变时调用的事件处理程序。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" |
[data-highlighted] | 高亮时存在 |
[data-disabled] | 禁用时存在 |
RadioGroup
用于分组多个 ContextMenu.RadioItems。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
modelValue | string | 组中选中项目的值。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
update:modelValue | [payload: string] | 当值改变时调用的事件处理程序。 |
RadioItem
可以像单选框一样控制和渲染的项目。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | boolean | 当为 true 时,阻止用户与项目交互。 | |
textValue | string | 用于类型提前的可选文本。默认情况下,类型提前行为将使用项目的 .textContent。当内容复杂或内部有非文本内容时使用。 | |
value* | string | 项目的唯一值。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
select | [event: Event] | 当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" |
[data-highlighted] | 高亮时存在 |
[data-disabled] | 禁用时存在 |
ItemIndicator
当父级 ContextMenu.CheckboxItem 或 ContextMenu.RadioItem 被勾选时渲染。您可以直接设置此元素的样式,也可以将其用作放置图标的包装器,或两者兼而有之。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
forceMount | boolean | 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" |
Separator
用于在上下文菜单中视觉上分隔项目。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
Sub
包含子菜单的所有部分。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
defaultOpen | boolean | 子菜单首次渲染时的打开状态。当您不需要控制其打开状态时使用。 | |
open | boolean | 菜单的受控打开状态。可以作为 v-model:open 使用。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
update:open | [payload: boolean] | 子菜单打开状态改变时调用的事件处理程序。 |
默认插槽
| 插槽参数 | Payload | 描述 |
|---|---|---|
open | boolean | 当前打开状态 |
SubTrigger
打开子菜单的项目。必须在 ContextMenu.Sub 内部渲染。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | boolean | 当为 true 时,阻止用户与项目交互。 | |
textValue | string | 用于类型提前的可选文本。默认情况下,类型提前行为将使用项目的 .textContent。当内容复杂或内部有非文本内容时使用。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "open" | "closed" |
[data-highlighted] | 高亮时存在 |
[data-disabled] | 禁用时存在 |
SubContent
当子菜单打开时弹出的组件。必须在 ContextMenu.Sub 内部渲染。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
alignFlip | boolean | 当与边界发生碰撞时翻转对齐方式。仅在 prioritizePosition 为 true 时可能发生。 | |
alignOffset | number | 从 start 或 end 对齐选项的像素偏移量。 | |
arrowPadding | number | 箭头与内容边缘之间的填充。如果您的内容有 border-radius,这将防止它溢出角。 | |
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
avoidCollisions | boolean | 当为 true 时,覆盖侧边和对齐偏好以防止与边界边缘碰撞。 | |
collisionBoundary | Element | (Element | null)[] | null | 用作碰撞边界的元素。默认情况下是视口,但您可以提供额外的元素以包含在此检查中。 | |
collisionPadding | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>> | 碰撞检测应发生的边界边缘的像素距离。接受一个数字(所有边相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。 | |
disableUpdateOnLayoutShift | boolean | 是否在布局偏移时禁用内容更新位置。 | |
forceMount | boolean | 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 | |
hideWhenDetached | boolean | 当触发器完全被遮挡时是否隐藏内容。 | |
loop | boolean | 当为 true 时,键盘导航将从最后一个项目循环到第一个,反之亦然。 | |
positionStrategy | 'fixed' | 'absolute' | 要使用的 CSS position 属性类型。 | |
prioritizePosition | boolean | 强制内容在视口内定位。可能会与参考元素重叠,这可能不是期望的。 | |
reference | ReferenceElement | 将作为浮动元素定位参考的自定义元素或虚拟元素。如果提供,它将替换默认锚点元素。 | |
sideOffset | number | 与触发器的像素距离。 | |
sticky | 'partial' | 'always' | 对齐轴上的粘性行为。partial 将使内容保持在边界内,只要触发器至少部分在边界内,而 always 将无论如何都使内容保持在边界内。 | |
updatePositionStrategy | 'always' | 'optimized' | 在每个动画帧上更新浮动元素位置的策略。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
closeAutoFocus | [event: Event] | 关闭时自动聚焦时调用的事件处理程序。可以阻止。 |
entryFocus | [event: Event] | 容器被聚焦时调用的事件处理程序。可以阻止。 |
escapeKeyDown | [event: KeyboardEvent] | Escape 键按下时调用的事件处理程序。可以阻止。 |
focusOutside | [event: FocusOutsideEvent] | 焦点移出 DismissableLayer 时调用的事件处理程序。可以阻止。 |
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent] | 当 DismissableLayer 外部发生交互时调用的事件处理程序。具体来说,当 pointerdown 事件发生在外部或焦点移出时。可以阻止。 |
openAutoFocus | [event: Event] | 打开时自动聚焦时调用的事件处理程序。可以阻止。 |
pointerDownOutside | [event: PointerDownOutsideEvent] | 当 pointerdown 事件发生在 DismissableLayer 外部时调用的事件处理程序。可以阻止。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS 变量
| 变量 | 描述 |
|---|---|
--reka-context-menu-content-transform-origin | 从内容和箭头位置/偏移量计算的 transform-origin |
--reka-context-menu-content-available-width | 触发器和边界边缘之间剩余的宽度 |
--reka-context-menu-content-available-height | 触发器和边界边缘之间剩余的高度 |
--reka-context-menu-trigger-width | 触发器的宽度 |
--reka-context-menu-trigger-height | 触发器的高度 |
示例
使用子菜单
您可以结合使用 ContextMenuSub 及其部分来创建子菜单。
<script setup lang="ts">
import {
ContextMenuContent,
ContextMenuItem,
ContextMenuLabel,
ContextMenuPortal,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuSub>
<ContextMenuSubTrigger>Sub menu →</ContextMenuSubTrigger>
<ContextMenuPortal>
<ContextMenuSubContent>
<ContextMenuItem>Sub menu item</ContextMenuItem>
<ContextMenuItem>Sub menu item</ContextMenuItem>
<ContextMenuArrow />
</ContextMenuSubContent>
</ContextMenuPortal>
</ContextMenuSub>
<ContextMenuSeparator />
<ContextMenuItem>…</ContextMenuItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
使用禁用项
您可以通过 data-disabled 属性为禁用项添加特殊样式。
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuItem
class="ContextMenuItem"
disabled
>
…
</ContextMenuItem>
<ContextMenuItem class="ContextMenuItem">
…
</ContextMenuItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
.ContextMenuItem[data-disabled] {
color: gainsboro;
}
使用分隔符
使用 Separator 部分在项目之间添加分隔符。
<script setup lang="ts">
import {
ContextMenuContent,
ContextMenuItem,
ContextMenuPortal,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuTrigger,
} from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem>…</ContextMenuItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
使用标签
使用 Label 部分帮助标记一个部分。
<script setup lang="ts">
import {
ContextMenuContent,
ContextMenuItem,
ContextMenuLabel,
ContextMenuPortal,
ContextMenuRoot,
ContextMenuTrigger,
} from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuLabel>Label</ContextMenuLabel>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuItem>…</ContextMenuItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
使用复选框项
使用 CheckboxItem 部分添加一个可勾选的项目。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuItemIndicator,
ContextMenuPortal,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuTrigger,
} from 'reka-ui'
const checked = ref(true)
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuItem>…</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuCheckboxItem v-model="checked">
<ContextMenuItemIndicator>
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator>
Checkbox item
</ContextMenuCheckboxItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
带单选框项
使用 RadioGroup 和 RadioItem 部分添加一个可在其他项目之间选择的项目。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuItemIndicator,
ContextMenuPortal,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuRoot,
ContextMenuSeparator,
ContextMenuTrigger,
} from 'reka-ui'
const color = ref('blue')
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuRadioGroup v-model="color">
<ContextMenuRadioItem value="red">
<ContextMenuItemIndicator>
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator>
Red
</ContextMenuRadioItem>
<ContextMenuRadioItem value="blue">
<ContextMenuItemIndicator>
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator>
Blue
</ContextMenuRadioItem>
<ContextMenuRadioItem value="green">
<ContextMenuItemIndicator>
<Icon icon="radix-icons:check" />
</ContextMenuItemIndicator>
Green
</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
带复杂项
您可以在 Item 部分中添加额外的装饰元素,例如图片。
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent>
<ContextMenuItem>
<img src="…">
Adolfo Hess
</ContextMenuItem>
<ContextMenuItem>
<img src="…">
Miyah Myles
</ContextMenuItem>
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
限制内容/子内容大小
您可能希望限制内容(或子内容)的宽度,使其与触发器(或子触发器)的宽度匹配。您可能还希望限制其高度不超过视口。
我们暴露了几个 CSS 自定义属性,例如 --reka-context-menu-trigger-width 和 --reka-context-menu-content-available-height 来支持这一点。使用它们来限制内容尺寸。
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent class="ContextMenuContent">
…
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
.ContextMenuContent {
width: var(--reka-context-menu-trigger-width);
max-height: var(--reka-context-menu-content-available-height);
}
感知源动画
我们暴露了一个 CSS 自定义属性 --reka-context-menu-content-transform-origin。使用它来根据 side、sideOffset、align、alignOffset 和任何碰撞从计算出的原点动画内容。
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent class="ContextMenuContent">
…
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
.ContextMenuContent {
transform-origin: var(--reka-context-menu-content-transform-origin);
animation: scaleIn 0.5s ease-out;
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0);
}
to {
opacity: 1;
transform: scale(1);
}
}
感知碰撞动画
我们暴露了 data-side 和 data-align 属性。它们的值将在运行时改变以反映碰撞。使用它们来创建感知碰撞和方向的动画。
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
<ContextMenuRoot>
<ContextMenuTrigger>…</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent class="ContextMenuContent">
…
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>
.ContextMenuContent {
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.ContextMenuContent[data-side="top"] {
animation-name: slideUp;
}
.ContextMenuContent[data-side="bottom"] {
animation-name: slideDown;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
可访问性
使用 漫游 tabindex 来管理菜单项之间的焦点移动。
键盘交互
| 按键 | 描述 |
|---|---|
Space | 激活聚焦的项目。 |
Enter | 激活聚焦的项目。 |
ArrowDown | 将焦点移至下一个项目。 |
ArrowUp | 将焦点移至上一个项目。 |
ArrowRight ArrowLeft | 当焦点在 ContextMenu.SubTrigger 上时,根据阅读方向打开或关闭子菜单。 |
Esc | 关闭上下文菜单。 |