下拉菜单

一个常见的下拉菜单按钮设计模式的可访问下拉菜单。菜单使用循环的 tabIndex 来进行焦点管理。

导入

import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuArrow,
  DropdownMenuGroup,
  DropdownMenuLabel,
  DropdownMenuDivider,
  DropdownMenuItem,
  DropdownMenuItemTrigger,
  DropdownMenuItemIndicator,
  DropdownMenuCheckboxItem,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
} from "@resolid/react-ui";
  • DropdownMenu: 包含下拉菜单的所有部分。
  • DropdownMenuTrigger: 包装将打开下拉菜单的控件。
  • DropdownMenuContent: 打开下拉菜单时弹出的组件。
  • DropdownMenuArrow: 可选的箭头元素,可与菜单内容一起渲染。
  • DropdownMenuGroup: 用于对多个 DropdownMenuItem 进行分组。
  • DropdownMenuLabel: 用于渲染标签。使用箭头键无法聚焦。
  • DropdownMenuDivider: 菜单项和组之间的可视分隔符。
  • DropdownMenuItem: 包含下拉菜单项的组件。
  • DropdownMenuItemTrigger: 包装将打开子菜单的控件。
  • DropdownMenuRadioGroup: 用于对多个 DropdownMenuRadioItem 进行分组。
  • DropdownMenuRadioItem: 一个可以像单选按钮一样进行控制和渲染的项目。
  • DropdownMenuCheckboxItem: 一个可以像复选框一样进行控制和渲染的项目。
  • DropdownMenuItemIndicator: 在父级 DropdownMenuCheckboxItemDropdownMenuRadioItem 被选中项目时呈现的视觉指示器。

普通菜单

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button color={"neutral"}>普通菜单</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent className={"text-sm"}>
    <DropdownMenuItem>
      新标签页<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+T</span>
    </DropdownMenuItem>
    <DropdownMenuItem>
      打开新窗口<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+N</span>
    </DropdownMenuItem>
    <DropdownMenuItem disabled>
      打开新的无痕式窗口<span className={"ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+N</span>
    </DropdownMenuItem>
    <DropdownMenuDivider />
    <DropdownMenuItem>
      关闭窗口<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⇧+⌘+W</span>
    </DropdownMenuItem>
    <DropdownMenuItem>
      关闭标签页<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+W</span>
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

多级菜单

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button color={"neutral"}>多级菜单</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent className={"text-sm"}>
    <DropdownMenuArrow />
    <DropdownMenuItem>新建</DropdownMenuItem>
    <DropdownMenuItem>打开</DropdownMenuItem>
    <DropdownMenuDivider />
    <DropdownMenu>
      <DropdownMenuItemTrigger>分享</DropdownMenuItemTrigger>
      <DropdownMenuContent className={"text-sm"}>
        <DropdownMenuItem>邮件</DropdownMenuItem>
        <DropdownMenuItem>短信</DropdownMenuItem>
        <DropdownMenu>
          <DropdownMenuItemTrigger>社交媒体</DropdownMenuItemTrigger>
          <DropdownMenuContent className={"text-sm"}>
            <DropdownMenu>
              <DropdownMenuItemTrigger>微信</DropdownMenuItemTrigger>
              <DropdownMenuContent className={"text-sm"}>
                <DropdownMenuItem>聊天</DropdownMenuItem>
                <DropdownMenuItem>朋友圈</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <DropdownMenuItem>微博</DropdownMenuItem>
            <DropdownMenuItem>抖音</DropdownMenuItem>
            <DropdownMenuItem>知乎</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </DropdownMenuContent>
    </DropdownMenu>
  </DropdownMenuContent>
</DropdownMenu>

复选组菜单

const [bookmarksChecked, setBookmarksChecked] = React.useState(true);
const [urlsChecked, setUrlsChecked] = React.useState(false);

return (
  <DropdownMenu closeOnSelect={false}>
    <DropdownMenuTrigger asChild>
      <Button color={"neutral"}>复选框菜单</Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent className={"text-sm"}>
      <DropdownMenuGroup>
        <DropdownMenuLabel>选项</DropdownMenuLabel>
        <DropdownMenuCheckboxItem checked={bookmarksChecked} onChange={setBookmarksChecked}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </DropdownMenuItemIndicator>
          显示书签栏<div className="ml-auto pl-5 text-sm text-fg-muted">⌘+B</div>
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem checked={urlsChecked} onChange={setUrlsChecked}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </DropdownMenuItemIndicator>
          显示路径
        </DropdownMenuCheckboxItem>
      </DropdownMenuGroup>
    </DropdownMenuContent>
  </DropdownMenu>
);

单选组菜单

const [bookmarksChecked, setBookmarksChecked] = React.useState(true);
const [urlsChecked, setUrlsChecked] = React.useState(false);

return (
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button color={"neutral"}>复选框菜单</Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent className={"text-sm"}>
      <DropdownMenuGroup>
        <DropdownMenuLabel>选项</DropdownMenuLabel>
        <DropdownMenuCheckboxItem checked={bookmarksChecked} onChange={setBookmarksChecked}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </DropdownMenuItemIndicator>
          显示书签栏<div className="ml-auto pl-5 text-sm text-fg-muted">⌘+B</div>
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem checked={urlsChecked} onChange={setUrlsChecked}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"check"} />
          </DropdownMenuItemIndicator>
          显示路径
        </DropdownMenuCheckboxItem>
      </DropdownMenuGroup>
    </DropdownMenuContent>
  </DropdownMenu>
);

访问内部状态

<DropdownMenu closeOnBlur={false}>
  {({ opened }) => (
    <>
      <DropdownMenuTrigger asChild>
        <Button color={'neutral'}>{opened ? "关闭" : "打开"}弹出框</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent className={"text-sm"}>
        <DropdownMenuArrow />
        <DropdownMenuItem>新建</DropdownMenuItem>
        <DropdownMenuItem>打开</DropdownMenuItem>
      </DropdownMenuContent>
    </>
  )}
</DropdownMenu>

触发方式

<DropdownMenu trigger={'hover'}>
  <DropdownMenuTrigger asChild><Button color={'neutral'}>悬停菜单</Button></DropdownMenuTrigger>
  <DropdownMenuContent className={"text-sm"}>
    <DropdownMenuArrow />
    <DropdownMenuItem>新建</DropdownMenuItem>
    <DropdownMenuItem>打开</DropdownMenuItem>
    <DropdownMenuDivider />
    <DropdownMenu>
      <DropdownMenuItemTrigger>分享</DropdownMenuItemTrigger>
      <DropdownMenuContent className={"text-sm"}>
        <DropdownMenuItem>邮件</DropdownMenuItem>
        <DropdownMenuItem>短信</DropdownMenuItem>
        <DropdownMenu>
          <DropdownMenuItemTrigger>社交媒体</DropdownMenuItemTrigger>
          <DropdownMenuContent className={"text-sm"}>
            <DropdownMenu>
              <DropdownMenuItemTrigger>微信</DropdownMenuItemTrigger>
              <DropdownMenuContent className={"text-sm"}>
                <DropdownMenuItem>聊天</DropdownMenuItem>
                <DropdownMenuItem>朋友圈</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <DropdownMenuItem>微博</DropdownMenuItem>
            <DropdownMenuItem>抖音</DropdownMenuItem>
            <DropdownMenuItem>知乎</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </DropdownMenuContent>
    </DropdownMenu>
  </DropdownMenuContent>
</DropdownMenu>

复杂菜单

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

return (
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button color={"neutral"}>复杂菜单</Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent className={"text-sm"}>
      <DropdownMenuArrow />
      <DropdownMenuItem>
        新标签页<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+T</span>
      </DropdownMenuItem>
      <DropdownMenuItem>
        打开新窗口<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+N</span>
      </DropdownMenuItem>
      <DropdownMenuItem disabled>
        打开新的无痕式窗口<span className={"ml-auto pl-5 text-xs tracking-widest"}>⇧+⌘+N</span>
      </DropdownMenuItem>
      <DropdownMenuDivider />
      <DropdownMenuItem>
        关闭窗口<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⇧+⌘+W</span>
      </DropdownMenuItem>
      <DropdownMenuItem>
        关闭标签页<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+W</span>
      </DropdownMenuItem>
      <DropdownMenuItem>
        页面存储为...<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+S</span>
      </DropdownMenuItem>
      <DropdownMenuDivider />
      <DropdownMenu>
        <DropdownMenuItemTrigger>分享</DropdownMenuItemTrigger>
        <DropdownMenuContent className={"text-sm"}>
          <DropdownMenuItem>电子邮件</DropdownMenuItem>
          <DropdownMenuItem>手机短信</DropdownMenuItem>
          <DropdownMenuItem>隔空投送</DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
      <DropdownMenuDivider />
      <DropdownMenuItem>
        打印<span className={"ml-auto pl-5 text-xs tracking-widest text-fg-subtle"}>⌘+P</span>
      </DropdownMenuItem>
      <DropdownMenuDivider />
      <DropdownMenuCheckboxItem checked={bookmarksChecked} onChange={setBookmarksChecked}>
        <DropdownMenuItemIndicator>
          <SpriteIcon size={"1rem"} name={"check"} />
        </DropdownMenuItemIndicator>
        显示书签栏<div className="ml-auto pl-5 text-xs tracking-widest text-fg-subtle">⌘+B</div>
      </DropdownMenuCheckboxItem>
      <DropdownMenuCheckboxItem checked={urlsChecked} onChange={setUrlsChecked}>
        <DropdownMenuItemIndicator>
          <SpriteIcon size={"1rem"} name={"check"} />
        </DropdownMenuItemIndicator>
        显示路径
      </DropdownMenuCheckboxItem>
      <DropdownMenuDivider />
      <DropdownMenuRadioGroup value={account} onChange={setAccount}>
        <DropdownMenuLabel>账号</DropdownMenuLabel>
        <DropdownMenuRadioItem value={"张三"}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"dot"} />
          </DropdownMenuItemIndicator>
          张三
        </DropdownMenuRadioItem>
        <DropdownMenuRadioItem value={"李四"}>
          <DropdownMenuItemIndicator>
            <SpriteIcon size={"1rem"} name={"dot"} />
          </DropdownMenuItemIndicator>
          李四
        </DropdownMenuRadioItem>
      </DropdownMenuRadioGroup>
      <DropdownMenuDivider />
      <DropdownMenuItem>其他操作</DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
);

属性

属性trigger类型"click" | "hover"默认值'click'必须false
属性onClose类型() => void默认值-必须false
属性closeOnEsc类型boolean默认值true必须false
属性closeOnBlur类型boolean默认值true必须false
属性closeOnSelect类型boolean默认值true必须false
属性placement类型"top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end"默认值'bottom-start'必须false
属性duration类型number默认值'250'必须false
属性syncWidth类型boolean默认值true必须false