Reka UI logoReka
backdrop
组件

菜单栏

桌面应用程序中常见的视觉上持久的菜单,提供对一组一致命令的快速访问。

特性

  • 可受控或不受控。
  • 支持可配置阅读方向的子菜单。
  • 支持项目、标签和项目组。
  • 支持可勾选项目(单选或多选)。
  • 自定义侧边、对齐、偏移、碰撞处理。
  • 可选渲染一个指向箭头。
  • 焦点完全受控。
  • 完整的键盘导航。
  • 支持预输入搜索。

安装

从命令行安装此组件。

sh
$ npm add reka-ui

解构

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

vue
<script setup lang="ts">
import {
  MenubarArrow,
  MenubarCheckboxItem,
  MenubarContent,
  MenubarItem,
  MenubarItemIndicator,
  MenubarLabel,
  MenubarMenu,
  MenubarPortal,
  MenubarRadioGroup,
  MenubarRadioItem,
  MenubarRoot,
  MenubarSeparator,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from './'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger />
      <MenubarPortal>
        <MenubarContent>
          <MenubarLabel />
          <MenubarItem />

          <MenubarGroup>
            <MenubarItem />
          </MenubarGroup>

          <MenubarCheckboxItem>
            <MenubarItemIndicator />
          </MenubarCheckboxItem>

          <MenubarRadioGroup>
            <MenubarRadioItem>
              <MenubarItemIndicator />
            </MenubarRadioItem>
          </MenubarRadioGroup>

          <MenubarSub>
            <MenubarSubTrigger />
            <MenubarPortal>
              <MenubarSubContent />
            </MenubarPortal>
          </MenubarSub>

          <MenubarSeparator />
          <MenubarArrow />
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

API 参考

根组件

包含菜单栏的所有部分

属性默认类型
defaultValue
字符串

菜单在初次渲染时应打开的值。当您不需要控制值状态时使用。

dir
'从左到右' | '从右到左'

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

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

loop
false
布尔值

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

modelValue
字符串

要打开的菜单的受控值。可用作 v-model

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

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

插槽(默认)载荷
modelValue
字符串

当前输入值

一个顶级菜单项,包含一个触发器和内容组合。

属性默认类型
value
字符串

当导航菜单受控时,将项目与活动值关联的唯一值。

当不受控时,此 prop 会自动管理。

触发器

用于切换内容的按钮。默认情况下,MenubarContent 会根据触发器定位。

属性默认类型
as
'按钮'
作为标签 | 组件

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

asChild
布尔值

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

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

disabled
布尔值

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

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

传送门

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

属性默认类型
defer
布尔值

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

reference

disabled
布尔值

禁用传送并内联渲染组件

reference

forceMount
布尔值

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

to
字符串 | HTMLElement

Vue 原生传送组件属性 :to

reference

内容

菜单打开时弹出的组件。

属性默认类型
align
'开始'
'开始' | '居中' | '结束'

相对于触发器的首选对齐方式。当发生碰撞时可能会改变。

alignOffset
数字

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

arrowPadding
数字

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

as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

avoidCollisions
布尔值

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

collisionBoundary
元素 | (元素 | null)[] | null

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

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

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

disableUpdateOnLayoutShift
布尔值

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

forceMount
布尔值

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

hideWhenDetached
布尔值

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

loop
布尔值

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

positionStrategy
'固定' | '绝对'

要使用的 CSS position 属性类型。

prioritizePosition
布尔值

强制内容在视口内定位。

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

reference
ReferenceElement

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

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

side
'上' | '右' | '下' | '左'

打开时,相对于触发器渲染的首选侧边。当发生碰撞且启用 avoidCollisions 时,将反转。

sideOffset
数字

与触发器的像素距离。

sticky
'部分' | '始终'

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

updatePositionStrategy
'始终' | '优化'

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

事件触发载荷
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-menubar-content-transform-origin
从内容和箭头位置/偏移量计算的 transform-origin
--reka-menubar-content-available-width
触发器与边界边缘之间的剩余宽度
--reka-menubar-content-available-height
触发器与边界边缘之间的剩余高度
--reka-menubar-trigger-width
触发器的宽度
--reka-menubar-trigger-height
触发器的高度

箭头

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

属性默认类型
as
'svg'
作为标签 | 组件

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

asChild
布尔值

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

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

高度
5
数字

箭头的像素高度。

rounded
布尔值

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

宽度
10
数字

箭头的像素宽度。

项目

包含菜单栏项目的组件。

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

disabled
布尔值

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

textValue
字符串

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

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

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

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

用于将多个 MenubarItem 分组。

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

标签

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

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

复选框项目

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

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

disabled
布尔值

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

modelValue
假 | 真 | '不确定'

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

textValue
字符串

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

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

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

update:modelValue
[载荷: 布尔值]

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

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

单选组

用于将多个 MenubarRadioItem 分组。

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

modelValue
字符串

组中选中项目的值。

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

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

单选项目

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

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

disabled
布尔值

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

textValue
字符串

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

值*
字符串

项目的唯一值。

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

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

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

项目指示器

当父级 MenubarCheckboxItemMenubarRadioItem 被选中时渲染。您可以直接设置此元素的样式,也可以将其用作放置图标的包装器,或者两者兼可。

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

forceMount
布尔值

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

数据属性
[data-state]"选中" | "未选中"

分隔符

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

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

子菜单

包含子菜单的所有部分。

属性默认类型
defaultOpen
布尔值

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

open
布尔值

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

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

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

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

当前打开状态

子菜单触发器

一个用于打开子菜单的项目。必须在 MenubarSub 内部渲染。

属性默认类型
as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

disabled
布尔值

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

textValue
字符串

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

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

子菜单内容

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

属性默认类型
alignOffset
数字

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

arrowPadding
数字

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

as
'div'
作为标签 | 组件

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

asChild
布尔值

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

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

avoidCollisions
布尔值

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

collisionBoundary
元素 | (元素 | null)[] | null

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

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

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

disableUpdateOnLayoutShift
布尔值

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

forceMount
布尔值

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

hideWhenDetached
布尔值

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

loop
布尔值

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

positionStrategy
'固定' | '绝对'

要使用的 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]"开始" | "结束" | "居中"
[data-orientation]"垂直" | "水平"
CSS 变量描述
--reka-menubar-content-transform-origin
从内容和箭头位置/偏移量计算的 transform-origin
--reka-menubar-content-available-width
触发器与边界边缘之间的剩余宽度
--reka-menubar-content-available-height
触发器与边界边缘之间的剩余高度
--reka-menubar-trigger-width
触发器的宽度
--reka-menubar-trigger-height
触发器的高度

示例

带子菜单

您可以使用 MenubarSub 及其部分组合来创建子菜单。

vue
<script setup lang="ts">
import {
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarPortal,
  MenubarRoot,
  MenubarSeparator,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarItem>…</MenubarItem>
          <MenubarItem>…</MenubarItem>
          <MenubarSeparator />
          <MenubarSub>
            <MenubarSubTrigger>Sub menu →</MenubarSubTrigger>
            <MenubarPortal>
              <MenubarSubContent>
                <MenubarItem>Sub menu item</MenubarItem>
                <MenubarItem>Sub menu item</MenubarItem>
                <MenubarArrow />
              </MenubarSubContent>
            </MenubarPortal>
          </MenubarSub>
          <MenubarSeparator />
          <MenubarItem>…</MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

带禁用项目

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

vue
<script setup lang="ts">
import { MenubarContent, MenubarItem, MenubarMenu, MenubarPortal, MenubarRoot, MenubarTrigger } from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarItem
            class="MenubarItem"
            disabled
          >

          </MenubarItem>
          <MenubarItem class="MenubarItem">

          </MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>
css
/* styles.css */
.MenubarItem[data-disabled] {
  color: gainsboro;
}

带分隔符

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

vue
<script setup lang="ts">
import {
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarPortal,
  MenubarRoot,
  MenubarSeparator,
  MenubarTrigger,
} from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarItem>…</MenubarItem>
          <MenubarSeparator />
          <MenubarItem>…</MenubarItem>
          <MenubarSeparator />
          <MenubarItem>…</MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

带标签

使用 Label 部分帮助标记一个区域。

vue
<script setup lang="ts">
import {
  MenubarContent,
  MenubarItem,
  MenubarLabel,
  MenubarMenu,
  MenubarPortal,
  MenubarRoot,
  MenubarTrigger,
} from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarLabel>Label</MenubarLabel>
          <MenubarItem>…</MenubarItem>
          <MenubarItem>…</MenubarItem>
          <MenubarItem>…</MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

带复选框项目

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

vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  MenubarCheckboxItem,
  MenubarContent,
  MenubarItem,
  MenubarItemIndicator,
  MenubarMenu,
  MenubarPortal,
  MenubarRoot,
  MenubarSeparator,
  MenubarTrigger,
} from 'reka-ui'

const checked = ref(true)
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarItem>…</MenubarItem>
          <MenubarItem>…</MenubarItem>
          <MenubarSeparator />
          <MenubarCheckboxItem v-model="checked">
            <MenubarItemIndicator>
              <Icon icon="radix-icons:check" />
            </MenubarItemIndicator>
            Checkbox item
          </MenubarCheckboxItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

带单选项目

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

vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  MenubarCheckboxItem,
  MenubarContent,
  MenubarItem,
  MenubarItemIndicator,
  MenubarMenu,
  MenubarPortal,
  MenubarRadioGroup,
  MenubarRadioItem,
  MenubarRoot,
  MenubarSeparator,
  MenubarTrigger,
} from 'reka-ui'

const color = ref('blue')
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarRadioGroup v-model="color">
            <MenubarRadioItem value="red">
              <MenubarItemIndicator>
                <Icon icon="radix-icons:check" />
              </MenubarItemIndicator>
              Red
            </MenubarRadioItem>
            <MenubarRadioItem value="blue">
              <MenubarItemIndicator>
                <Icon icon="radix-icons:check" />
              </MenubarItemIndicator>
              Blue
            </MenubarRadioItem>
          </MenubarRadioGroup>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

带复杂项目

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

vue
<script setup lang="ts">
import { MenubarContent, MenubarItem, MenubarMenu, MenubarPortal, MenubarRoot, MenubarTrigger } from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent>
          <MenubarItem>
            <img src="…">
            Adolfo Hess
          </MenubarItem>
          <MenubarItem>
            <img src="…">
            Miyah Myles
          </MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>

限制内容/子内容大小

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

我们公开了几个 CSS 自定义属性,例如 --reka-menubar-trigger-width--reka-menubar-content-available-height 来支持此功能。使用它们来限制内容尺寸。

vue
<script setup lang="ts">
import { MenubarContent, MenubarItem, MenubarMenu, MenubarPortal, MenubarRoot, MenubarTrigger } from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger> Trigger </MenubarTrigger>
      <MenubarPortal>
        <MenubarContent
          class="MenubarContent"
          :side-offset="5"
          :align-offset="-3"
        >
          <MenubarItem> New Tab </MenubarItem>
        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>
css
/* styles.css */
.MenubarContent {
  width: var(--reka-menubar-trigger-width);
  max-height: var(--reka-menubar-content-available-height);
}

原点感知动画

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

vue
<script setup lang="ts">
import { MenubarContent, MenubarMenu, MenubarPortal, MenubarRoot, MenubarTrigger } from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent class="MenubarContent">

        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>
css
/* styles.css */
.MenubarContent {
  transform-origin: var(--reka-menubar-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 { MenubarContent, MenubarMenu, MenubarPortal, MenubarRoot, MenubarTrigger } from 'reka-ui'
</script>

<template>
  <MenubarRoot>
    <MenubarMenu>
      <MenubarTrigger>…</MenubarTrigger>
      <MenubarPortal>
        <MenubarContent class="MenubarContent">

        </MenubarContent>
      </MenubarPortal>
    </MenubarMenu>
  </MenubarRoot>
</template>
css
/* styles.css */
.MenubarContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.MenubarContent[data-side="top"] {
  animation-name: slideUp;
}
.MenubarContent[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);
  }
}

可访问性

遵循 菜单按钮 WAI-ARIA 设计模式,并使用 roving tabindex 管理菜单项之间的焦点移动。

键盘交互

描述
空格键
当焦点位于 MenubarTrigger 上时,打开菜单栏并聚焦第一个项目。
当焦点位于某个项目上时,激活该项目。
回车键
当焦点位于 MenubarTrigger 上时,打开关联菜单。
当焦点位于某个项目上时,激活该项目。
向下箭头键
当焦点位于 MenubarTrigger 上时,打开关联菜单。
当焦点在项目上时,将焦点移到下一个项目。
向上箭头键
当焦点在项目上时,将焦点移到上一个项目。
向右箭头键向左箭头键
当焦点位于 MenubarTrigger 上时,将焦点移动到下一个或上一个项目。
当焦点位于 MenubarSubTrigger 上时,根据阅读方向打开或关闭子菜单。
当焦点位于 MenubarContent 内部时,打开菜单栏中的下一个菜单。
Esc键
关闭当前打开的菜单,并将焦点移动到其 MenubarTrigger