组件

上下文菜单

显示位于指针处的菜单,由右键点击或长按触发。

import React from 'react';
import * as ContextMenu from '@radix-ui/react-context-menu';
import { DotFilledIcon, CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons';
import './styles.css';
const ContextMenuDemo = () => {
const [bookmarksChecked, setBookmarksChecked] = React.useState(true);
const [urlsChecked, setUrlsChecked] = React.useState(false);
const [person, setPerson] = React.useState('pedro');
return (
<ContextMenu.Root>
<ContextMenu.Trigger className="ContextMenuTrigger">Right-click here.</ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent" sideOffset={5} align="end">
<ContextMenu.Item className="ContextMenuItem">
Back <div className="RightSlot">⌘+[</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem" disabled>
Forward <div className="RightSlot">⌘+]</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">
Reload <div className="RightSlot">⌘+R</div>
</ContextMenu.Item>
<ContextMenu.Sub>
<ContextMenu.SubTrigger className="ContextMenuSubTrigger">
More Tools
<div className="RightSlot">
<ChevronRightIcon />
</div>
</ContextMenu.SubTrigger>
<ContextMenu.Portal>
<ContextMenu.SubContent className="ContextMenuSubContent" sideOffset={2} alignOffset={-5} >
<ContextMenu.Item className="ContextMenuItem">
Save Page As… <div className="RightSlot">⌘+S</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">Create Shortcut…</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">Name Window…</ContextMenu.Item>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.Item className="ContextMenuItem">Developer Tools</ContextMenu.Item>
</ContextMenu.SubContent>
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.CheckboxItem className="ContextMenuCheckboxItem" checked={bookmarksChecked} onCheckedChange={setBookmarksChecked} >
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<CheckIcon />
</ContextMenu.ItemIndicator>
Show Bookmarks <div className="RightSlot">⌘+B</div>
</ContextMenu.CheckboxItem>
<ContextMenu.CheckboxItem className="ContextMenuCheckboxItem" checked={urlsChecked} onCheckedChange={setUrlsChecked} >
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<CheckIcon />
</ContextMenu.ItemIndicator>
Show Full URLs
</ContextMenu.CheckboxItem>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.Label className="ContextMenuLabel">People</ContextMenu.Label>
<ContextMenu.RadioGroup value={person} onValueChange={setPerson}>
<ContextMenu.RadioItem className="ContextMenuRadioItem" value="pedro">
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<DotFilledIcon />
</ContextMenu.ItemIndicator>
Pedro Duarte
</ContextMenu.RadioItem>
<ContextMenu.RadioItem className="ContextMenuRadioItem" value="colm">
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<DotFilledIcon />
</ContextMenu.ItemIndicator>
Colm Tuite
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};
export default ContextMenuDemo;

特性

    支持具有可配置阅读方向的子菜单。

    支持项目、标签和项目组。

    支持可选中项目(单个或多个),并具有可选的不确定状态。

    支持模态和非模态模式。

    自定义侧边、对齐方式、偏移量、碰撞处理。

    焦点得到完全管理。

    完整的键盘导航。

    支持类型输入。

    关闭和分层行为高度可定制。

    在触摸设备上通过长按触发

安装

从命令行安装组件。

npm install @radix-ui/react-context-menu

结构

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

import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger />
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Label />
<ContextMenu.Item />
<ContextMenu.Group>
<ContextMenu.Item />
</ContextMenu.Group>
<ContextMenu.CheckboxItem>
<ContextMenu.ItemIndicator />
</ContextMenu.CheckboxItem>
<ContextMenu.RadioGroup>
<ContextMenu.RadioItem>
<ContextMenu.ItemIndicator />
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
<ContextMenu.Sub>
<ContextMenu.SubTrigger />
<ContextMenu.Portal>
<ContextMenu.SubContent />
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator />
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);

API 参考

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

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

属性类型默认值
dir
枚举
无默认值
onOpenChange
函数
无默认值
模态
布尔值
true

触发器

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

属性类型默认值
asChild
布尔值
false
禁用
布尔值
false
数据属性
[data-state]"open" |"closed"

门户

使用时,将内容部分传送至body

属性类型默认值
forceMount
布尔值
无默认值
容器
HTMLElement
document.body

内容

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

属性类型默认值
asChild
布尔值
false
循环
布尔值
false
onCloseAutoFocus
函数
无默认值
onEscapeKeyDown
函数
无默认值
onPointerDownOutside
函数
无默认值
onFocusOutside
函数
无默认值
onInteractOutside
函数
无默认值
forceMount
布尔值
无默认值
对齐偏移量
数字
0
避免碰撞
布尔值
true
碰撞边界
边界
[]
碰撞填充
数字 | 填充
0
粘性
枚举
"partial"
分离时隐藏
布尔值
false
数据属性
[data-state]"open" |"closed"
[data-side]"left" |"right" |"bottom" |"top"
[data-align]"start" |"end" |"center"
CSS 变量描述
--radix-context-menu-content-transform-origin根据内容和箭头位置/偏移量计算的transform-origin
--radix-context-menu-content-available-width触发器和边界边缘之间的剩余宽度
--radix-context-menu-content-available-height触发器和边界边缘之间的剩余高度
--radix-context-menu-trigger-width触发器的宽度
--radix-context-menu-trigger-height触发器的高度

箭头

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

属性类型默认值
asChild
布尔值
false
宽度
数字
10
高度
数字
5

项目

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

属性类型默认值
asChild
布尔值
false
禁用
布尔值
无默认值
onSelect
函数
无默认值
文本值
字符串
无默认值
数据属性
[data-highlighted]

突出显示时出现

[data-disabled]

禁用时出现

用于对多个ContextMenu.Item进行分组。

属性类型默认值
asChild
布尔值
false

标签

用于渲染标签。它将无法使用方向键聚焦。

属性类型默认值
asChild
布尔值
false

复选框项目

可以像复选框一样控制和渲染的项目。

属性类型默认值
asChild
布尔值
false
选中
布尔值 | 'indeterminate'
无默认值
onCheckedChange
函数
无默认值
禁用
布尔值
无默认值
onSelect
函数
无默认值
文本值
字符串
无默认值
数据属性
[data-state]"checked" |"unchecked" |"indeterminate"
[data-highlighted]

突出显示时出现

[data-disabled]

禁用时出现

单选组

用于对多个ContextMenu.RadioItem进行分组。

属性类型默认值
asChild
布尔值
false
字符串
无默认值
onValueChange
函数
无默认值

单选项目

可以像单选按钮一样控制和渲染的项目。

属性类型默认值
asChild
布尔值
false
*
字符串
无默认值
禁用
布尔值
无默认值
onSelect
函数
无默认值
文本值
字符串
无默认值
数据属性
[data-state]"checked" |"unchecked" |"indeterminate"
[data-highlighted]

突出显示时出现

[data-disabled]

禁用时出现

项目指示器

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

属性类型默认值
asChild
布尔值
false
forceMount
布尔值
无默认值
数据属性
[data-state]"checked" |"unchecked" |"indeterminate"

分隔符

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

属性类型默认值
asChild
布尔值
false

子菜单

包含子菜单的所有部分。

属性类型默认值
默认打开
布尔值
无默认值
打开
布尔值
无默认值
onOpenChange
函数
无默认值

子菜单触发器

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

属性类型默认值
asChild
布尔值
false
禁用
布尔值
无默认值
文本值
字符串
无默认值
数据属性
[data-state]"open" |"closed"
[data-highlighted]

突出显示时出现

[data-disabled]

禁用时出现

子菜单内容

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

属性类型默认值
asChild
布尔值
false
循环
布尔值
false
onEscapeKeyDown
函数
无默认值
onPointerDownOutside
函数
无默认值
onFocusOutside
函数
无默认值
onInteractOutside
函数
无默认值
forceMount
布尔值
无默认值
侧边偏移量
数字
0
对齐偏移量
数字
0
避免碰撞
布尔值
true
碰撞边界
边界
[]
碰撞填充
数字 | 填充
0
箭头填充
数字
0
粘性
枚举
"partial"
分离时隐藏
布尔值
false
数据属性
[data-state]"open" |"closed"
[data-side]"left" |"right" |"bottom" |"top"
[data-align]"start" |"end" |"center"
CSS 变量描述
--radix-context-menu-content-transform-origin根据内容和箭头位置/偏移量计算的transform-origin
--radix-context-menu-content-available-width触发器和边界边缘之间的剩余宽度
--radix-context-menu-content-available-height触发器和边界边缘之间的剩余高度
--radix-context-menu-trigger-width触发器的宽度
--radix-context-menu-trigger-height触发器的高度

示例

带有子菜单

您可以通过结合使用ContextMenu.Sub及其各个部分来创建子菜单。

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Sub>
<ContextMenu.SubTrigger>Sub menu →</ContextMenu.SubTrigger>
<ContextMenu.Portal>
<ContextMenu.SubContent>
<ContextMenu.Item>Sub menu item</ContextMenu.Item>
<ContextMenu.Item>Sub menu item</ContextMenu.Item>
<ContextMenu.Arrow />
</ContextMenu.SubContent>
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

带有禁用项

您可以通过data-disabled属性为禁用项添加特殊样式。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item className="ContextMenuItem" disabled>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem"></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuItem[data-disabled] {
color: gainsboro;
}

带有分隔符

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

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

带有标签

使用Label部分帮助标记某个部分。

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Label>Label</ContextMenu.Label>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

带有复选框项目

使用CheckboxItem部分添加可以勾选的项目。

import React from 'react';
import { CheckIcon } from '@radix-ui/react-icons';
import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => {
const [checked, setChecked] = React.useState(true);
return (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.CheckboxItem checked={checked} onCheckedChange={setChecked} >
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Checkbox item
</ContextMenu.CheckboxItem>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};

带有单选项目

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

import React from 'react';
import { CheckIcon } from '@radix-ui/react-icons';
import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => {
const [color, setColor] = React.useState('blue');
return (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.RadioGroup value={color} onValueChange={setColor}>
<ContextMenu.RadioItem value="red">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Red
</ContextMenu.RadioItem>
<ContextMenu.RadioItem value="blue">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Blue
</ContextMenu.RadioItem>
<ContextMenu.RadioItem value="green">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Green
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};

带有复杂项目

您可以在Item部分中添加额外的装饰元素,例如图像。

import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item>
<img src="" />
Adolfo Hess
</ContextMenu.Item>
<ContextMenu.Item>
<img src="" />
Miyah Myles
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);

约束内容/子内容大小

您可能希望约束内容(或子内容)的宽度,使其与触发器(或子触发器)的宽度匹配。您可能还想约束其高度,使其不超过视口。

我们公开了几个 CSS 自定义属性,例如--radix-context-menu-trigger-width--radix-context-menu-content-available-height来支持这一点。使用它们来约束内容尺寸。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuContent {
width: var(--radix-context-menu-trigger-width);
max-height: var(--radix-context-menu-content-available-height);
}

源感知动画

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

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuContent {
transform-origin: var(--radix-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属性。它们的值将在运行时更改以反映碰撞。使用它们创建碰撞和方向感知动画。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* 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
关闭上下文菜单
上一个可折叠
下一个对话框