¥Menu Bar
桌面应用中常见的视觉持久菜单,可快速访问一组一致的命令。
import * as React from "react";import { Menubar } from "radix-ui";import { CheckIcon, ChevronRightIcon, DotFilledIcon, } from "@radix-ui/react-icons";import "./styles.css";const RADIO_ITEMS = ["Andy", "Benoît", "Luis"];const CHECK_ITEMS = ["Always Show Bookmarks Bar", "Always Show Full URLs"];const MenubarDemo = () => {const [checkedSelection, setCheckedSelection] = React.useState([CHECK_ITEMS[1],]);const [radioSelection, setRadioSelection] = React.useState(RADIO_ITEMS[2]);return (<Menubar.Root className="MenubarRoot"><Menubar.Menu><Menubar.Trigger className="MenubarTrigger">File</Menubar.Trigger><Menubar.Portal><Menubar.Content className="MenubarContent" align="start" sideOffset={5} alignOffset={-3} ><Menubar.Item className="MenubarItem">New Tab <div className="RightSlot">⌘ T</div></Menubar.Item><Menubar.Item className="MenubarItem">New Window <div className="RightSlot">⌘ N</div></Menubar.Item><Menubar.Item className="MenubarItem" disabled>New Incognito Window</Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Sub><Menubar.SubTrigger className="MenubarSubTrigger">Share<div className="RightSlot"><ChevronRightIcon /></div></Menubar.SubTrigger><Menubar.Portal><Menubar.SubContent className="MenubarSubContent" alignOffset={-5} ><Menubar.Item className="MenubarItem">Email Link</Menubar.Item><Menubar.Item className="MenubarItem">Messages</Menubar.Item><Menubar.Item className="MenubarItem">Notes</Menubar.Item></Menubar.SubContent></Menubar.Portal></Menubar.Sub><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem">Print… <div className="RightSlot">⌘ P</div></Menubar.Item></Menubar.Content></Menubar.Portal></Menubar.Menu><Menubar.Menu><Menubar.Trigger className="MenubarTrigger">Edit</Menubar.Trigger><Menubar.Portal><Menubar.Content className="MenubarContent" align="start" sideOffset={5} alignOffset={-3} ><Menubar.Item className="MenubarItem">Undo <div className="RightSlot">⌘ Z</div></Menubar.Item><Menubar.Item className="MenubarItem">Redo <div className="RightSlot">⇧ ⌘ Z</div></Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Sub><Menubar.SubTrigger className="MenubarSubTrigger">Find<div className="RightSlot"><ChevronRightIcon /></div></Menubar.SubTrigger><Menubar.Portal><Menubar.SubContent className="MenubarSubContent" alignOffset={-5} ><Menubar.Item className="MenubarItem">Search the web…</Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem">Find…</Menubar.Item><Menubar.Item className="MenubarItem">Find Next</Menubar.Item><Menubar.Item className="MenubarItem">Find Previous</Menubar.Item></Menubar.SubContent></Menubar.Portal></Menubar.Sub><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem">Cut</Menubar.Item><Menubar.Item className="MenubarItem">Copy</Menubar.Item><Menubar.Item className="MenubarItem">Paste</Menubar.Item></Menubar.Content></Menubar.Portal></Menubar.Menu><Menubar.Menu><Menubar.Trigger className="MenubarTrigger">View</Menubar.Trigger><Menubar.Portal><Menubar.Content className="MenubarContent" align="start" sideOffset={5} alignOffset={-14} >{CHECK_ITEMS.map((item) => (<Menubar.CheckboxItem className="MenubarCheckboxItem inset" key={item} checked={checkedSelection.includes(item)} onCheckedChange={() => setCheckedSelection((current) => current.includes(item) ? current.filter((el) => el !== item) : current.concat(item), ) } ><Menubar.ItemIndicator className="MenubarItemIndicator"><CheckIcon /></Menubar.ItemIndicator>{item}</Menubar.CheckboxItem>))}<Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem inset">Reload <div className="RightSlot">⌘ R</div></Menubar.Item><Menubar.Item className="MenubarItem inset" disabled>Force Reload <div className="RightSlot">⇧ ⌘ R</div></Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem inset">Toggle Fullscreen</Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem inset">Hide Sidebar</Menubar.Item></Menubar.Content></Menubar.Portal></Menubar.Menu><Menubar.Menu><Menubar.Trigger className="MenubarTrigger">Profiles</Menubar.Trigger><Menubar.Portal><Menubar.Content className="MenubarContent" align="start" sideOffset={5} alignOffset={-14} ><Menubar.RadioGroup value={radioSelection} onValueChange={setRadioSelection} >{RADIO_ITEMS.map((item) => (<Menubar.RadioItem className="MenubarRadioItem inset" key={item} value={item} ><Menubar.ItemIndicator className="MenubarItemIndicator"><DotFilledIcon /></Menubar.ItemIndicator>{item}</Menubar.RadioItem>))}<Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem inset">Edit…</Menubar.Item><Menubar.Separator className="MenubarSeparator" /><Menubar.Item className="MenubarItem inset">Add Profile…</Menubar.Item></Menubar.RadioGroup></Menubar.Content></Menubar.Portal></Menubar.Menu></Menubar.Root>);};export default MenubarDemo;
Can be controlled or uncontrolled.
Supports submenus with configurable reading direction.
Supports items, labels, groups of items.
Supports checkable items (single or multiple).
Customize side, alignment, offsets, collision handling.
Optionally render a pointing arrow.
Focus is fully managed.
Full keyboard navigation.
Typeahead support.
¥Installation
从命令行安装组件。
¥Install the component from your command line.
¥Anatomy
导入所有部分并将它们组合在一起。
¥Import all parts and piece them together.
¥API Reference
¥Root
包含菜单栏的所有部分。
¥Contains all the parts of a menubar.
¥Menu
顶层菜单项,包含触发器及其内容组合。
¥A top level menu item, contains a trigger with content combination.
¥Trigger
切换内容的按钮。默认情况下,Menubar.Content
将根据触发器进行定位。
¥The button that toggles the content. By default, the Menubar.Content
will position itself against the trigger.
¥Portal
使用时,将内容部分传送到 body
中。
¥When used, portals the content part into the body
.
¥Content
在菜单打开时弹出的组件。
¥The component that pops out when a menu is open.
¥Arrow
一个可选的箭头元素,用于与菜单栏菜单一起渲染。这可以用来帮助在视觉上将触发器与 Menubar.Content
链接起来。必须在 Menubar.Content
中渲染。
¥An optional arrow element to render alongside a menubar menu. This can be used to help visually link the trigger with the Menubar.Content
. Must be rendered inside Menubar.Content
.
¥Item
包含菜单栏项的组件。
¥The component that contains the menubar items.
¥Group
用于对多个 Menubar.Item
进行分组。
¥Used to group multiple Menubar.Item
s.
¥Label
用于渲染标签。它无法通过方向键获得焦点。
¥Used to render a label. It won't be focusable using arrow keys.
可以像复选框一样控制和渲染的项目。
¥An item that can be controlled and rendered like a checkbox.
用于对多个 Menubar.RadioItem
进行分组。
¥Used to group multiple Menubar.RadioItem
s.
可以像单选按钮一样控制和渲染的项目。
¥An item that can be controlled and rendered like a radio.
当父级 Menubar.CheckboxItem
或 Menubar.RadioItem
被选中时渲染。你可以直接设置此元素的样式,也可以将其用作封装器来放置图标,或者两者兼而有之。
¥Renders when the parent Menubar.CheckboxItem
or Menubar.RadioItem
is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.
¥Separator
用于在菜单栏菜单中以视觉方式分隔项目。
¥Used to visually separate items in a menubar menu.
包含子菜单的所有部分。
¥Contains all the parts of a submenu.
打开子菜单的项目。必须在 Menubar.Sub
中渲染。
¥An item that opens a submenu. Must be rendered inside Menubar.Sub
.
在子菜单打开时弹出的组件。必须在 Menubar.Sub
中渲染。
¥The component that pops out when a submenu is open. Must be rendered inside Menubar.Sub
.
¥Examples
¥With submenus
你可以将 Menubar.Sub
及其各个部分结合使用来创建子菜单。
¥You can create submenus by using Menubar.Sub
in combination with its parts.
¥With disabled items
你可以通过 data-disabled
属性为禁用项目添加特殊样式。
¥You can add special styles to disabled items via the data-disabled
attribute.
¥With separators
使用 Separator
组件在项目之间添加分隔符。
¥Use the Separator
part to add a separator between items.
¥With labels
使用 Label
组件帮助标记某个部分。
¥Use the Label
part to help label a section.
¥With checkbox items
使用 CheckboxItem
组件添加可勾选的项目。
¥Use the CheckboxItem
part to add an item that can be checked.
¥With radio items
使用 RadioGroup
和 RadioItem
部件添加一个可在众多选项中勾选的项目。
¥Use the RadioGroup
and RadioItem
parts to add an item that can be checked amongst others.
¥With complex items
你可以在 Item
部件中添加额外的装饰元素,例如图片。
¥You can add extra decorative elements in the Item
parts, such as images.
¥Constrain the content/sub-content size
你可能需要限制内容(或子内容)的宽度,使其与触发器(或子触发器)的宽度匹配。你可能还需要限制其高度,使其不超过视口。
¥You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport.
为了支持此功能,我们公开了几个 CSS 自定义属性,例如 --radix-menubar-trigger-width
和 --radix-menubar-content-available-height
。使用它们来限制内容尺寸。
¥We expose several CSS custom properties such as --radix-menubar-trigger-width
and --radix-menubar-content-available-height
to support this. Use them to constrain the content dimensions.
¥Origin-aware animations
我们公开了一个 CSS 自定义属性 --radix-menubar-content-transform-origin
。使用它来根据 side
、sideOffset
、align
、alignOffset
以及任何碰撞,从其计算出的原点为内容设置动画。
¥We expose a CSS custom property --radix-menubar-content-transform-origin
. Use it to animate the content from its computed origin based on side
, sideOffset
, align
, alignOffset
and any collisions.
¥Collision-aware animations
我们公开了 data-side
和 data-align
属性。它们的值将在运行时更改以反映碰撞。使用它们来创建碰撞和方向感知动画。
¥We expose data-side
and data-align
attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations.
¥Accessibility
遵循 菜单按钮 WAI-ARIA 设计模式 并使用 移动 tabindex 管理菜单项之间的焦点移动。
¥Adheres to the Menu Button WAI-ARIA design pattern and uses roving tabindex to manage focus movement among menu items.
¥Keyboard Interactions