Menu 菜单

基于 BrConfigProvider 全局主题配置的菜单组件,复刻 shadcn-vue 设计体系,支持多级嵌套、快捷键标注和键盘导航。本组件主要用于实现上下文菜单(Right-click Context Menu)。

组件特性

  • 🎨 主题适配:深度集成 BrConfigProvider,支持 CSS 变量配置背景、前景、圆角、阴影等。
  • 📋 多级嵌套:支持无限层级的子菜单嵌套。
  • ⌨️ 键盘导航:完整支持 Tab、Arrow Up/Down/Left/Right、Enter、Esc 等键位操作。
  • ⌨️ 快捷键:支持菜单项快捷键标注。
  • 📦 分组分隔:支持菜单分组和分隔线。
  • 🎯 边界检测:自动调整弹出位置,防止溢出视口。

基础用法

最简单的上下文菜单,包含几个基本操作。

<script setup lang="ts">
import {
  BrMenu,
  BrMenuTrigger,
  BrMenuContent,
  BrMenuItem,
  BrMenuSeparator,
} from '@breezeui/vue';
</script>

<template>
  <BrMenu>
    <BrMenuTrigger class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
      Right click here
    </BrMenuTrigger>
    <BrMenuContent class="w-64">
      <BrMenuItem inset>Back</BrMenuItem>
      <BrMenuItem inset disabled>Forward</BrMenuItem>
      <BrMenuItem inset>Reload</BrMenuItem>
      <BrMenuSeparator />
      <BrMenuItem inset>Save As...</BrMenuItem>
      <BrMenuItem inset>Print...</BrMenuItem>
    </BrMenuContent>
  </BrMenu>
</template>

复杂菜单

支持分组、图标、快捷键和多级嵌套的复杂上下文菜单,效果如图所示。

<script setup lang="ts">
import {
  BrMenu,
  BrMenuTrigger,
  BrMenuContent,
  BrMenuItem,
  BrMenuSeparator,
  BrMenuLabel,
  BrMenuGroup,
  BrMenuSub,
  BrMenuSubTrigger,
  BrMenuSubContent,
} from '@breezeui/vue';
import {
  User,
  CreditCard,
  Settings,
  Keyboard,
  Users,
  UserPlus,
  Mail,
  MessageSquare,
  PlusCircle,
  Plus,
  Github,
  LifeBuoy,
  Cloud,
  LogOut,
} from 'lucide-vue-next';
</script>

<template>
  <BrMenu>
    <BrMenuTrigger
      class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm font-medium"
    >
      Right-click in this area (Right click here)
    </BrMenuTrigger>
    <BrMenuContent class="w-64">
      <BrMenuItem inset>
        Back
        <template #shortcut>⌘[</template>
      </BrMenuItem>
      <BrMenuItem inset disabled>
        Forward
        <template #shortcut>⌘]</template>
      </BrMenuItem>
      <BrMenuItem inset>
        Reload
        <template #shortcut>⌘R</template>
      </BrMenuItem>
      <BrMenuSeparator />
      <BrMenuItem inset>
        Show Bookmarks Bar
        <template #shortcut>⌘⇧B</template>
      </BrMenuItem>
      <BrMenuItem inset>Show Full URLs</BrMenuItem>
      <BrMenuSeparator />
      <BrMenuLabel inset>People</BrMenuLabel>
      <BrMenuSeparator />
      <BrMenuGroup>
        <BrMenuItem>
          <User class="mr-2 h-4 w-4" />
          <span>Profile</span>
          <template #shortcut>⇧⌘P</template>
        </BrMenuItem>
        <BrMenuItem>
          <CreditCard class="mr-2 h-4 w-4" />
          <span>Billing</span>
          <template #shortcut>⌘B</template>
        </BrMenuItem>
        <BrMenuItem>
          <Settings class="mr-2 h-4 w-4" />
          <span>Settings</span>
          <template #shortcut>⌘S</template>
        </BrMenuItem>
        <BrMenuItem>
          <Keyboard class="mr-2 h-4 w-4" />
          <span>Keyboard shortcuts</span>
          <template #shortcut>⌘K</template>
        </BrMenuItem>
      </BrMenuGroup>
      <BrMenuSeparator />
      <BrMenuGroup>
        <BrMenuItem>
          <Users class="mr-2 h-4 w-4" />
          <span>Team</span>
        </BrMenuItem>
        <BrMenuSub>
          <BrMenuSubTrigger>
            <UserPlus class="mr-2 h-4 w-4" />
            <span>Invite users</span>
          </BrMenuSubTrigger>
          <BrMenuSubContent class="w-48">
            <BrMenuItem>
              <Mail class="mr-2 h-4 w-4" />
              <span>Email</span>
            </BrMenuItem>
            <BrMenuItem>
              <MessageSquare class="mr-2 h-4 w-4" />
              <span>Message</span>
            </BrMenuItem>
            <BrMenuSeparator />
            <BrMenuItem>
              <PlusCircle class="mr-2 h-4 w-4" />
              <span>More...</span>
            </BrMenuItem>
          </BrMenuSubContent>
        </BrMenuSub>
        <BrMenuItem>
          <Plus class="mr-2 h-4 w-4" />
          <span>New Team</span>
          <template #shortcut>⌘+T</template>
        </BrMenuItem>
      </BrMenuGroup>
      <BrMenuSeparator />
      <BrMenuItem>
        <Github class="mr-2 h-4 w-4" />
        <span>GitHub</span>
      </BrMenuItem>
      <BrMenuItem>
        <LifeBuoy class="mr-2 h-4 w-4" />
        <span>Support</span>
      </BrMenuItem>
      <BrMenuItem disabled>
        <Cloud class="mr-2 h-4 w-4" />
        <span>API</span>
      </BrMenuItem>
      <BrMenuSeparator />
      <BrMenuItem>
        <LogOut class="mr-2 h-4 w-4" />
        <span>Log out</span>
        <template #shortcut>⇧⌘Q</template>
      </BrMenuItem>
    </BrMenuContent>
  </BrMenu>
</template>

多级嵌套子菜单

支持使用 BrMenuSub 创建多级子菜单。

<script setup lang="ts">
import {
  BrMenu,
  BrMenuTrigger,
  BrMenuContent,
  BrMenuItem,
  BrMenuSub,
  BrMenuSubTrigger,
  BrMenuSubContent,
  BrMenuSeparator,
} from '@breezeui/vue';
import { ChevronRight } from 'lucide-vue-next';
</script>

<template>
  <BrMenu>
    <BrMenuTrigger class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
      Right click for Submenu
    </BrMenuTrigger>
    <BrMenuContent class="w-64">
      <BrMenuItem>Item 1</BrMenuItem>
      <BrMenuSub>
        <BrMenuSubTrigger>More Options</BrMenuSubTrigger>
        <BrMenuSubContent class="w-48">
          <BrMenuItem>Save</BrMenuItem>
          <BrMenuItem>Save As...</BrMenuItem>
          <BrMenuSeparator />
          <BrMenuSub>
            <BrMenuSubTrigger>Export</BrMenuSubTrigger>
            <BrMenuSubContent>
              <BrMenuItem>PDF</BrMenuItem>
              <BrMenuItem>HTML</BrMenuItem>
            </BrMenuSubContent>
          </BrMenuSub>
        </BrMenuSubContent>
      </BrMenuSub>
    </BrMenuContent>
  </BrMenu>
</template>

带快捷键标注

使用 shortcut 插槽或属性展示快捷键。

<script setup lang="ts">
import {
  BrMenu,
  BrMenuTrigger,
  BrMenuContent,
  BrMenuItem,
} from '@breezeui/vue';
</script>

<template>
  <BrMenu>
    <BrMenuTrigger class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
      Right click for Shortcuts
    </BrMenuTrigger>
    <BrMenuContent class="w-64">
      <BrMenuItem shortcut="⌘X">Cut</BrMenuItem>
      <BrMenuItem shortcut="⌘C">Copy</BrMenuItem>
      <BrMenuItem shortcut="⌘V">Paste</BrMenuItem>
    </BrMenuContent>
  </BrMenu>
</template>

主题定制

BrMenu 基于 BrConfigProvider 的 CSS 变量进行样式定制。

通过 BrConfigProvider 全局配置 Menu 的圆角、背景色、阴影等。

<script setup lang="ts">
import {
  BrConfigProvider,
  BrMenu,
  BrMenuTrigger,
  BrMenuContent,
  BrMenuItem,
} from '@breezeui/vue';
</script>

<template>
  <BrConfigProvider
    :theme="{
      popover: 'hsl(222.2 84% 4.9%)',
      popoverForeground: 'hsl(210 40% 98%)',
      border: 'hsl(217.2 32.6% 17.5%)',
      radius: 1, // 1rem
      zMenu: 100,
    }"
  >
    <BrMenu>
      <BrMenuTrigger class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
        Right click (Dark Theme Menu)
      </BrMenuTrigger>
      <BrMenuContent class="w-64">
        <BrMenuItem inset>Item 1</BrMenuItem>
        <BrMenuItem inset>Item 2</BrMenuItem>
        <BrMenuItem inset>Item 3</BrMenuItem>
      </BrMenuContent>
    </BrMenu>
  </BrConfigProvider>
</template>

API 参考

BrMenu (Root)

属性类型默认值说明
dir'ltr' | 'rtl'-阅读方向

BrMenuTrigger

属性类型默认值说明
disabledbooleanfalse是否禁用触发器

BrMenuContent

属性类型默认值说明
loopbooleanfalse键盘导航是否循环
alignOffsetnumber-对齐偏移量

BrMenuItem

属性类型默认值说明
disabledbooleanfalse是否禁用
insetbooleanfalse是否留出左侧图标空间
shortcutstring-快捷键文本

BrMenuSub

属性类型默认值说明
defaultOpenbooleanfalse默认是否展开
openboolean-受控展开状态