Reka UI 标志Reka
backdrop
组件

上下文菜单

在指针位置显示菜单,通过右键单击或长按触发。
在此处右键单击。

功能特性

  • 支持可配置阅读方向的子菜单。
  • 支持项目、标签、项目组。
  • 支持可勾选项目(单选或多选),并可选不确定状态。
  • 支持模态和非模态模式。
  • 自定义侧边、对齐方式、偏移量、碰撞处理。
  • 焦点完全受控。
  • 完整的键盘导航。
  • 支持预输入搜索。
  • 关闭和分层行为高度可定制。
  • 在触摸设备上通过长按触发

安装

从命令行安装此组件。

sh
$ npm add reka-ui

结构剖析

导入所有部分并将其组合。

vue
<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 参考

遵循 菜单 WAI-ARIA 设计模式 并使用 漫游 tabindex 来管理菜单项之间的焦点移动。

包含上下文菜单的所有部分。

属性默认类型
dir
'ltr' | 'rtl'

适用时,组合框的阅读方向。

如果省略,则全局继承自 ConfigProvider 或假定为 LTR(从左到右)阅读模式。

modal
true
布尔值

下拉菜单的模态。

当设置为 true 时,与外部元素的交互将被禁用,并且只有菜单内容对屏幕阅读器可见。

事件触发载荷
update:open
[载荷: 布尔值]

子菜单打开状态改变时调用的事件处理程序。

触发器

打开上下文菜单的区域。将其包裹在你希望上下文菜单在右键单击(或使用相关键盘快捷键)时打开的目标元素周围。

属性默认类型
as
'span'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
false
布尔值

当设置为 true 时,右键单击将不会打开上下文菜单。

请注意,这也会恢复原生的上下文菜单。

数据属性
[data-state]"打开" | "关闭"

传送门

使用时,将内容部分传送到 body 中。

属性默认类型
defer
布尔值

延迟解析 Teleport 目标,直到应用程序的其他部分挂载(需要 Vue 3.5.0+)

reference

disabled
布尔值

禁用传送并内联渲染组件

reference

forceMount
布尔值

当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。

to
字符串 | HTMLElement

Vue 原生传送组件属性 :to

reference

内容

在打开的上下文菜单中弹出的组件。

属性默认类型
alignOffset
0
数字

startend 对齐选项的像素偏移量。

as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

avoidCollisions
true
布尔值

当为 true 时,覆盖侧边和对齐偏好,以防止与边界边缘发生碰撞。

collisionBoundary
[]
Element | (Element | null)[] | null

用作碰撞边界的元素。默认情况下是视口,但您可以提供其他元素以包含在此检查中。

collisionPadding
0
数字 | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>

碰撞检测应发生的距边界边缘的像素距离。接受一个数字(所有边相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。

disableUpdateOnLayoutShift
布尔值

当布局发生偏移时,是否禁用更新内容位置。

forceMount
布尔值

当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。

hideWhenDetached
false
布尔值

当触发器完全被遮挡时,是否隐藏内容。

loop
布尔值

当为 true 时,键盘导航将从最后一个项目循环到第一个项目,反之亦然。

positionStrategy
'fixed' | 'absolute'

要使用的 CSS position 属性类型。

prioritizePosition
布尔值

强制内容在视口内定位。

可能与参考元素重叠,这可能不是期望的结果。

reference
ReferenceElement

将设置为浮动元素定位参考的自定义元素或虚拟元素。

如果提供,它将替换默认的锚点元素。

sticky
'partial'
'部分' | '始终'

对齐轴上的粘性行为。partial 将使内容保持在边界内,只要触发器至少部分在边界内;而 "always" 则无论如何都会将内容保持在边界内。

事件触发载荷
closeAutoFocus
[事件: Event]

关闭时自动聚焦调用的事件处理程序。可阻止其默认行为。

escapeKeyDown
[事件: KeyboardEvent]

按下 Esc 键时调用的事件处理程序。可阻止其默认行为。

focusOutside
[事件: FocusOutsideEvent]

当焦点移出 DismissableLayer 时调用的事件处理程序。可阻止其默认行为。

interactOutside
[事件: PointerDownOutsideEvent | FocusOutsideEvent]

DismissableLayer 外部发生交互时调用的事件处理程序。具体来说,当 pointerdown 事件在外部发生或焦点移出时。可阻止其默认行为。

pointerDownOutside
[事件: PointerDownOutsideEvent]

pointerdown 事件在 DismissableLayer 外部发生时调用的事件处理程序。可阻止其默认行为。

数据属性
[data-state]"打开" | "关闭"
[data-side]"左" | "右" | "下" | "上"
[data-align]"开始" | "结束" | "居中"
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
触发器的高度

箭头

一个可选的箭头元素,用于与子菜单一起渲染。这可以用来帮助视觉上将触发项与 ContextMenu.Content 连接起来。必须在 ContextMenu.Content 内部渲染。

属性默认类型
as
'svg'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

高度
5
数字

箭头的像素高度。

rounded
布尔值

当为 true 时,渲染圆角版本的箭头。不适用于 as/asChild

宽度
10
数字

箭头的像素宽度。

项目

包含上下文菜单项目的组件。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

textValue
string

用于即时搜索的可选文本。默认情况下,即时搜索行为将使用项目的 .textContent
当内容复杂或包含非文本内容时使用此项。

事件触发载荷
select
[事件: Event]

当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。
在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。

数据属性
[data-highlighted]高亮时存在
[data-disabled]禁用时存在

用于将多个 ContextMenu.Item 组合在一起。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

标签

用于渲染标签。它不能通过箭头键聚焦。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

复选框项目

一个可受控并像复选框一样渲染的项目。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

modelValue
假 | 真 | '不确定'

项目的受控选中状态。可用作 v-model

textValue
string

用于即时搜索的可选文本。默认情况下,即时搜索行为将使用项目的 .textContent
当内容复杂或包含非文本内容时使用此项。

事件触发载荷
select
[事件: Event]

当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。
在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。

update:modelValue
[载荷: 布尔值]

值改变时调用的事件处理程序。

数据属性
[data-state]"已选中" | "未选中" | "不确定"
[data-highlighted]高亮时存在
[data-disabled]禁用时存在

单选组

用于将多个 ContextMenu.RadioItem 组合在一起。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

modelValue
string

组中选中项目的值。

事件触发载荷
update:modelValue
[载荷: 字符串]

值改变时调用的事件处理程序。

单选项目

一个可受控并像单选按钮一样渲染的项目。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

textValue
string

用于即时搜索的可选文本。默认情况下,即时搜索行为将使用项目的 .textContent
当内容复杂或包含非文本内容时使用此项。

值*
string

项目的唯一值。

事件触发载荷
select
[事件: Event]

当用户选择项目(通过鼠标或键盘)时调用的事件处理程序。
在此处理程序中调用 event.preventDefault 将阻止在选择该项目时菜单关闭。

数据属性
[data-state]"已选中" | "未选中" | "不确定"
[data-highlighted]高亮时存在
[data-disabled]禁用时存在

项目指示器

当父级 ContextMenu.CheckboxItemContextMenu.RadioItem 被选中时渲染。你可以直接对此元素进行样式设置,也可以将其用作放置图标的包装器,或者两者兼可。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

forceMount
布尔值

当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。

数据属性
[data-state]"已选中" | "未选中" | "不确定"

分隔符

用于在上下文菜单中视觉上分隔项目。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

子菜单

包含子菜单的所有部分。

属性默认类型
defaultOpen
布尔值

子菜单在初始渲染时的打开状态。当您不需要控制其打开状态时使用。

open
布尔值

菜单的受控打开状态。可用作 v-model:open

事件触发载荷
update:open
[载荷: 布尔值]

子菜单打开状态改变时调用的事件处理程序。

插槽(默认)载荷
open
布尔值

当前打开状态

子菜单触发器

一个打开子菜单的项目。必须在 ContextMenu.Sub 内部渲染。

属性默认类型
as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

textValue
string

用于即时搜索的可选文本。默认情况下,即时搜索行为将使用项目的 .textContent
当内容复杂或包含非文本内容时使用此项。

数据属性
[data-state]"打开" | "关闭"
[data-highlighted]高亮时存在
[data-disabled]禁用时存在

子菜单内容

子菜单打开时弹出的组件。必须在 ContextMenu.Sub 内部渲染。

属性默认类型
alignOffset
数字

startend 对齐选项的像素偏移量。

arrowPadding
数字

箭头与内容边缘之间的内边距。如果您的内容有 border-radius,这将防止它溢出角落。

as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可通过 asChild 覆盖。

asChild
布尔值

更改默认渲染元素为作为子项传递的元素,合并它们的属性和行为。

阅读我们的 组合指南了解更多详情。

avoidCollisions
布尔值

当为 true 时,覆盖侧边和对齐偏好,以防止与边界边缘发生碰撞。

collisionBoundary
Element | (Element | null)[] | null

用作碰撞边界的元素。默认情况下是视口,但您可以提供其他元素以包含在此检查中。

collisionPadding
数字 | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>

碰撞检测应发生的距边界边缘的像素距离。接受一个数字(所有边相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。

disableUpdateOnLayoutShift
布尔值

当布局发生偏移时,是否禁用更新内容位置。

forceMount
布尔值

当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。

hideWhenDetached
布尔值

当触发器完全被遮挡时,是否隐藏内容。

loop
布尔值

当为 true 时,键盘导航将从最后一个项目循环到第一个项目,反之亦然。

positionStrategy
'fixed' | 'absolute'

要使用的 CSS position 属性类型。

prioritizePosition
布尔值

强制内容在视口内定位。

可能与参考元素重叠,这可能不是期望的结果。

reference
ReferenceElement

将设置为浮动元素定位参考的自定义元素或虚拟元素。

如果提供,它将替换默认的锚点元素。

sideOffset
数字

与触发器的像素距离。

sticky
'部分' | '始终'

对齐轴上的粘性行为。partial 将使内容保持在边界内,只要触发器至少部分在边界内;而 "always" 则无论如何都会将内容保持在边界内。

updatePositionStrategy
'始终' | '优化'

在每个动画帧更新浮动元素位置的策略。

事件触发载荷
closeAutoFocus
[事件: Event]

关闭时自动聚焦调用的事件处理程序。可阻止其默认行为。

entryFocus
[事件: Event]

容器获得焦点时调用的事件处理程序。可阻止其默认行为。

escapeKeyDown
[事件: KeyboardEvent]

按下 Esc 键时调用的事件处理程序。可阻止其默认行为。

focusOutside
[事件: FocusOutsideEvent]

当焦点移出 DismissableLayer 时调用的事件处理程序。可阻止其默认行为。

interactOutside
[事件: PointerDownOutsideEvent | FocusOutsideEvent]

DismissableLayer 外部发生交互时调用的事件处理程序。具体来说,当 pointerdown 事件在外部发生或焦点移出时。可阻止其默认行为。

openAutoFocus
[事件: Event]

打开时自动聚焦调用的事件处理程序。可阻止其默认行为。

pointerDownOutside
[事件: PointerDownOutsideEvent]

pointerdown 事件在 DismissableLayer 外部发生时调用的事件处理程序。可阻止其默认行为。

数据属性
[data-state]"打开" | "关闭"
[data-side]"左" | "右" | "下" | "上"
[data-align]"开始" | "结束" | "居中"
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 及其各部分来创建子菜单。

vue
<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 属性为禁用项目添加特殊样式。

vue
<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>
css
/* styles.css */
.ContextMenuItem[data-disabled] {
  color: gainsboro;
}

带分隔符

使用 Separator 部分在项目之间添加分隔符。

vue
<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 部分帮助标记一个区域。

vue
<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 部分添加一个可勾选的项目。

vue
<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>

带单选项目

使用 RadioGroupRadioItem 部分添加一个可在其他项目中选中的项目。

vue
<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 部分添加额外的装饰元素,例如图片。

vue
<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 来支持此功能。使用它们来限制内容尺寸。

vue
<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>
css
/* styles.css */
.ContextMenuContent {
  width: var(--reka-context-menu-trigger-width);
  max-height: var(--reka-context-menu-content-available-height);
}

原点感知动画

我们公开了一个 CSS 自定义属性 --reka-context-menu-content-transform-origin。使用它根据 sidesideOffsetalignalignOffset 和任何碰撞从其计算出的原点来动画化内容。

vue
<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>
css
/* styles.css */
.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-sidedata-align 属性。它们的值将在运行时改变以反映碰撞。使用它们来创建碰撞和方向感知的动画。

vue
<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>
css
/* styles.css */
.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 来管理菜单项之间的焦点移动。

键盘交互

描述
空格键
激活聚焦的项目。
回车键
激活聚焦的项目。
向下箭头键
将焦点移动到下一个项目。
向上箭头键
将焦点移动到上一个项目。
向右箭头键向左箭头键
当焦点位于 ContextMenu.SubTrigger 时,根据阅读方向打开或关闭子菜单。
Esc键
关闭上下文菜单