右键菜单

查看源代码

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

演示

当指针是笔或触摸时,在大约 700ms 的长压期间,右键菜单也会打开。

右键点击显示菜单
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@resolid/react-ui";

export default function App() {
  return (
    <ContextMenu>
      <ContextMenuTrigger
        className={
          "border-bd-normal flex h-32 select-none items-center rounded-md border border-dashed p-6"
        }
      >
        右键点击显示菜单
      </ContextMenuTrigger>
      <ContextMenuContent className={"text-sm"}>
        <ContextMenuItem>
          新标签页
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+T</span>
        </ContextMenuItem>
        <ContextMenuItem>
          打开新窗口
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+N</span>
        </ContextMenuItem>
        <ContextMenuItem disabled>
          打开新的无痕式窗口
          <span className={"ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+N</span>
        </ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem>
          关闭窗口
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+W</span>
        </ContextMenuItem>
        <ContextMenuItem>
          关闭标签页
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+W</span>
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  );
}

用法

import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuLabel,
  ContextMenuSeparator,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuCheckboxItem,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuSubTrigger,
} from "@resolid/react-ui";
  • ContextMenu: 包含菜单的所有部分。
  • ContextMenuTrigger: 包装将打开右键菜单的控件。
  • ContextMenuContent: 打开菜单时弹出的组件。
  • ContextMenuGroup: 用于对多个 ContextMenuItem 进行分组。
  • ContextMenuLabel: 用于渲染标签。使用方向键无法聚焦。
  • ContextMenuSeparator: 菜单项和组之间的可视分隔符。
  • ContextMenuItem: 包含菜单项的组件。
  • ContextMenuRadioGroup: 用于对多个 ContextMenuRadioItem 进行分组。
  • ContextMenuRadioItem: 一个可以像单选按钮一样进行控制和渲染的项目。
  • ContextMenuCheckboxItem: 一个可以像复选框一样进行控制和渲染的项目。
  • ContextMenuItemIndicator: 在父级 ContextMenuCheckboxItemContextMenuRadioItem 被选中项目时呈现的视觉指示器。
  • ContextMenuSubTrigger: 包装将打开子菜单的控件。
<ContextMenu>
  <ContextMenuTrigger />
  <ContextMenuContent>
    <ContextMenuItem />
    <ContextMenuSeparator />
    <ContextMenuGroup>
      <ContextMenuLabel />
      <ContextMenuItem />
    </ContextMenuGroup>
    <ContextMenuCheckboxItem>
      <ContextMenuItemIndicator />
    </ContextMenuCheckboxItem>
    <ContextMenuRadioGroup>
      <ContextMenuRadioItem>
        <ContextMenuItemIndicator />
      </ContextMenuRadioItem>
    </ContextMenuRadioGroup>
    <ContextMenu>
      <ContextMenuSubTrigger />
      <ContextMenuContent />
    </ContextMenu>
  </ContextMenuContent>
</ContextMenu>

特点

  • 遵循 WAI ARIA Menu 设计模式。
  • 长按触摸设备即可触发。
  • 支持项目、标签、项目组。
  • 支持具有可选不确定状态的可检查项目(单个或多个)。
  • 完整的键盘导航。
  • 支持禁用项目。
  • 打字以允许通过键入文本进行聚焦项目。
  • 焦点得到全面管理。

举例

多级菜单

要显示多级菜单,请渲染另一个 ContextMenu 组件并使用 ContextMenuSubTrigger 组件打开子菜单。

右键点击显示菜单
import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuSubTrigger,
} from "@resolid/react-ui";

export default function App() {
  return (
    <ContextMenu>
      <ContextMenuTrigger
        className={
          "border-bd-normal flex h-32 select-none items-center rounded-md border border-dashed p-6"
        }
      >
        右键点击显示菜单
      </ContextMenuTrigger>
      <ContextMenuContent className={"text-sm"}>
        <ContextMenuItem label={"New Tab"}>新建标签页</ContextMenuItem>
        <ContextMenuItem label={"New Window"}>打开新窗口</ContextMenuItem>
        <ContextMenuItem>打开新的无痕式窗口</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenu>
          <ContextMenuSubTrigger label={"Share"}>分享</ContextMenuSubTrigger>
          <ContextMenuContent className={"text-sm"}>
            <ContextMenuItem label={"Email"}>邮件</ContextMenuItem>
            <ContextMenuItem label={"SMS"}>短信</ContextMenuItem>
            <ContextMenu>
              <ContextMenuSubTrigger>社交媒体</ContextMenuSubTrigger>
              <ContextMenuContent className={"text-sm"}>
                <ContextMenu>
                  <ContextMenuSubTrigger>微信</ContextMenuSubTrigger>
                  <ContextMenuContent className={"text-sm"}>
                    <ContextMenuItem>聊天</ContextMenuItem>
                    <ContextMenuItem>朋友圈</ContextMenuItem>
                  </ContextMenuContent>
                </ContextMenu>
                <ContextMenuItem>微博</ContextMenuItem>
                <ContextMenuItem>抖音</ContextMenuItem>
                <ContextMenuItem>知乎</ContextMenuItem>
              </ContextMenuContent>
            </ContextMenu>
          </ContextMenuContent>
        </ContextMenu>
        <ContextMenuSeparator />
        <ContextMenu>
          <ContextMenuSubTrigger label={"Tools"}>更多工具</ContextMenuSubTrigger>
          <ContextMenuContent className={"text-sm"}>
            <ContextMenuItem>保存页面为...</ContextMenuItem>
            <ContextMenuItem>创建快捷方式</ContextMenuItem>
            <ContextMenuSeparator />
            <ContextMenuItem>开发者工具</ContextMenuItem>
          </ContextMenuContent>
        </ContextMenu>
      </ContextMenuContent>
    </ContextMenu>
  );
}

分组菜单

使用 ContextMenuGroup 组件对相关菜单项进行分组。

右键点击显示菜单
import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuGroup,
  ContextMenuLabel,
  ContextMenuSeparator,
} from "@resolid/react-ui";

export default function App() {
  return (
    <ContextMenu>
      <ContextMenuTrigger
        className={
          "border-bd-normal flex h-32 select-none items-center rounded-md border border-dashed p-6"
        }
      >
        右键点击显示菜单
      </ContextMenuTrigger>
      <ContextMenuContent className={"text-sm"}>
        <ContextMenuGroup>
          <ContextMenuLabel>Sort</ContextMenuLabel>
          <ContextMenuItem>Date</ContextMenuItem>
          <ContextMenuItem>Name</ContextMenuItem>
          <ContextMenuItem>Type</ContextMenuItem>
        </ContextMenuGroup>
        <ContextMenuSeparator />
        <ContextMenuGroup>
          <ContextMenuLabel>Workspace</ContextMenuLabel>
          <ContextMenuItem>Minimap</ContextMenuItem>
          <ContextMenuItem>Search</ContextMenuItem>
          <ContextMenuItem>Sidebar</ContextMenuItem>
        </ContextMenuGroup>
      </ContextMenuContent>
    </ContextMenu>
  );
}

复杂菜单

右键点击显示菜单
import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
  ContextMenuItemIndicator,
  ContextMenuSubTrigger,
  ContextMenuRadioGroup,
  ContextMenuLabel,
  ContextMenuRadioItem,
} from "@resolid/react-ui";
import { useState } from "react";
import { SpriteIcon } from "~/components/sprite-icon";

export default function App() {
  const [bookmarksChecked, setBookmarksChecked] = useState(true);
  const [urlsChecked, setUrlsChecked] = useState(false);
  const [account, setAccount] = useState("张三");

  return (
    <ContextMenu>
      <ContextMenuTrigger
        className={
          "border-bd-normal flex h-32 select-none items-center rounded-md border border-dashed p-6"
        }
      >
        右键点击显示菜单
      </ContextMenuTrigger>
      <ContextMenuContent className={"text-sm"}>
        <ContextMenuItem>
          新标签页
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+T</span>
        </ContextMenuItem>
        <ContextMenuItem>
          打开新窗口
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+N</span>
        </ContextMenuItem>
        <ContextMenuItem disabled>
          打开新的无痕式窗口
          <span className={"ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+N</span>
        </ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem>
          关闭窗口
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+W</span>
        </ContextMenuItem>
        <ContextMenuItem>
          关闭标签页
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+W</span>
        </ContextMenuItem>
        <ContextMenuItem>
          页面存储为...
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+S</span>
        </ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenu>
          <ContextMenuSubTrigger>分享</ContextMenuSubTrigger>
          <ContextMenuContent className={"text-sm"}>
            <ContextMenuItem>电子邮件</ContextMenuItem>
            <ContextMenuItem>手机短信</ContextMenuItem>
            <ContextMenuItem>隔空投送</ContextMenuItem>
          </ContextMenuContent>
        </ContextMenu>
        <ContextMenuSeparator />
        <ContextMenuItem>
          打印
          <span className={"text-fg-subtle ml-auto pl-5 text-xs tracking-widest"}>⌘+P</span>
        </ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuCheckboxItem checked={bookmarksChecked} onChange={setBookmarksChecked}>
          <ContextMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </ContextMenuItemIndicator>
          显示书签栏
          <div className="text-fg-subtle ml-auto pl-5 text-xs tracking-widest">⌘+B</div>
        </ContextMenuCheckboxItem>
        <ContextMenuCheckboxItem checked={urlsChecked} onChange={setUrlsChecked}>
          <ContextMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </ContextMenuItemIndicator>
          显示路径
        </ContextMenuCheckboxItem>
        <ContextMenuSeparator />
        <ContextMenuRadioGroup value={account} onChange={setAccount}>
          <ContextMenuLabel>账号</ContextMenuLabel>
          <ContextMenuRadioItem value={"张三"}>
            <ContextMenuItemIndicator>
              <SpriteIcon size={"1rem"} name={"dot"} />
            </ContextMenuItemIndicator>
            张三
          </ContextMenuRadioItem>
          <ContextMenuRadioItem value={"李四"}>
            <ContextMenuItemIndicator>
              <SpriteIcon size={"1rem"} name={"dot"} />
            </ContextMenuItemIndicator>
            李四
          </ContextMenuRadioItem>
        </ContextMenuRadioGroup>
        <ContextMenuSeparator />
        <ContextMenuItem>其他操作</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  );
}

属性

ContextMenu

属性duration简介

动画持续时间

类型number默认值250必须false
属性closeOnSelect简介

选择项目后, 菜单将关闭

类型boolean默认值true必须false
属性open简介

受控打开状态

类型boolean默认值-必须false
属性defaultOpen简介

初始渲染时的默认打开状态

类型boolean默认值false必须false
属性onOpenChange简介

打开状态改变时调用

类型(open: boolean) => void默认值-必须false

Item

属性label简介

用于菜单的提前导航文本。如果未提供,将使用菜单项的文本内容

类型string默认值-必须false
属性closeOnSelect简介

选择项目后, 菜单将关闭

类型boolean默认值-必须false
属性onSelect简介

当用户选择一个项目(通过鼠标或键盘)时调用事件处理程序

类型() => void默认值-必须false
属性disabled简介

该项目是否被禁用

类型boolean默认值false必须false

CheckboxItem

属性label简介

用于菜单的提前导航文本。如果未提供,将使用菜单项的文本内容

类型string默认值-必须false
属性closeOnSelect简介

选择项目后, 菜单将关闭

类型boolean默认值-必须false
属性onSelect简介

当用户选择一个项目(通过鼠标或键盘)时调用事件处理程序

类型() => void默认值-必须false
属性checked简介

项目的受控选中状态

类型false | true | "indeterminate"默认值-必须false
属性onChange简介

项目选中状态更改时调用的事件处理程序

类型(checked: CheckedState) => void默认值-必须false
属性disabled简介

该项目是否被禁用

类型boolean默认值false必须false

RadioGroup

属性value简介

要选中的菜单单选项目的控制值

类型string | number默认值-必须false
属性onChange简介

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

类型((value: string | number) => void)默认值-必须false

RadioItem

属性label简介

用于菜单的提前导航文本。如果未提供,将使用菜单项的文本内容

类型string默认值-必须false
属性closeOnSelect简介

选择项目后, 菜单将关闭

类型boolean默认值-必须false
属性onSelect简介

当用户选择一个项目(通过鼠标或键盘)时调用事件处理程序

类型() => void默认值-必须false
属性value简介

菜单单选项的价值

类型string | number默认值-必须true
属性disabled简介

该项目是否被禁用

类型boolean默认值false必须false

建议更改此页面