#Dropdown Menu 下拉菜单
基于 BrConfigProvider 实现全局主题配置,支持多方向、嵌套子菜单、自定义触发方式的企业级下拉菜单组件。
#组件特性
- 🛠️ 多方向弹出:支持向上、下、左、右四个方向弹出,自动调整以适应屏幕边缘。
- 📋 嵌套子菜单:支持无限级嵌套的子菜单,适用于复杂的层级结构。
- ⌨️ 快捷键支持:可为菜单项配置快捷键显示,提升键盘操作体验。
- 🖱️ 多触发方式:支持点击(click)、悬浮(hover)、右键(contextmenu)等多种触发方式。
- 🎨 主题定制:基于
BrConfigProvider支持全局主题定制,同时支持 TailwindCSS 局部样式覆盖。
#基础用法
最基础的下拉菜单展示。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrDropdownMenuSeparator,
BrButton
} from '@breezeui/vue'
</script>
<template>
<BrDropdownMenu>
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline">Open Menu</BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent>
<BrDropdownMenuItem>Profile</BrDropdownMenuItem>
<BrDropdownMenuItem>Billing</BrDropdownMenuItem>
<BrDropdownMenuItem>Settings</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem>Logout</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</template>#位置
支持 align 和 side 属性控制弹出位置,支持 12 个不同的方向。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrButton
} from '@breezeui/vue'
const positions = [
[
{ label: 'Top Start', side: 'top', align: 'start' },
{ label: 'Top', side: 'top', align: 'center' },
{ label: 'Top End', side: 'top', align: 'end' },
],
[
{ label: 'Right Start', side: 'right', align: 'start' },
{ label: 'Right', side: 'right', align: 'center' },
{ label: 'Right End', side: 'right', align: 'end' },
],
[
{ label: 'Bottom End', side: 'bottom', align: 'end' },
{ label: 'Bottom', side: 'bottom', align: 'center' },
{ label: 'Bottom Start', side: 'bottom', align: 'start' },
],
[
{ label: 'Left End', side: 'left', align: 'end' },
{ label: 'Left', side: 'left', align: 'center' },
{ label: 'Left Start', side: 'left', align: 'start' },
]
] as const
</script>
<template>
<div class="flex flex-col items-center gap-4 py-8">
<div v-for="(row, i) in positions" :key="i" class="flex flex-wrap justify-center gap-4">
<BrDropdownMenu v-for="pos in row" :key="pos.label">
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline" class="w-[120px]">{{ pos.label }}</BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent :side="pos.side" :align="pos.align">
<BrDropdownMenuItem>Option 1</BrDropdownMenuItem>
<BrDropdownMenuItem>Option 2</BrDropdownMenuItem>
<BrDropdownMenuItem>Option 3</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</div>
</div>
</template>#复杂示例
结合了图标、快捷键、分割线、嵌套子菜单、禁用状态、自定义样式的复杂应用场景。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrDropdownMenuSeparator,
BrDropdownMenuSub,
BrDropdownMenuSubTrigger,
BrDropdownMenuSubContent,
BrButton
} from '@breezeui/vue'
import {
Cloud,
CreditCard,
Github,
Keyboard,
LifeBuoy,
LogOut,
Mail,
MessageSquare,
Plus,
PlusCircle,
Settings,
User,
UserPlus,
} from 'lucide-vue-next'
</script>
<template>
<BrDropdownMenu>
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline">Complex Menu Example</BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent class="w-56" align="end" :side-offset="8">
<div class="px-2 py-1.5 text-sm font-normal">
<div class="flex flex-col space-y-1">
<p class="text-sm font-medium leading-none">breezeui</p>
<p class="text-xs leading-none text-muted-foreground">
breezeui@example.com
</p>
</div>
</div>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem shortcut="⇧⌘P">
<User class="mr-2 h-4 w-4" />
<span>Profile Page</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem shortcut="⌘B">
<CreditCard class="mr-2 h-4 w-4" />
<span>Billing Info</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem shortcut="⌘S">
<Settings class="mr-2 h-4 w-4" />
<span>System Settings</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem shortcut="⌘K">
<Keyboard class="mr-2 h-4 w-4" />
<span>Shortcut Configuration</span>
</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuSub>
<BrDropdownMenuSubTrigger>
<UserPlus class="mr-2 h-4 w-4" />
<span>Invite Team Members</span>
</BrDropdownMenuSubTrigger>
<BrDropdownMenuSubContent>
<BrDropdownMenuItem>
<Mail class="mr-2 h-4 w-4" />
<span>Via Email</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem>
<MessageSquare class="mr-2 h-4 w-4" />
<span>Via SMS</span>
</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem>
<PlusCircle class="mr-2 h-4 w-4" />
<span>More Invite Options...</span>
</BrDropdownMenuItem>
</BrDropdownMenuSubContent>
</BrDropdownMenuSub>
<BrDropdownMenuItem>
<Plus class="mr-2 h-4 w-4" />
<span>New Team</span>
</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem>
<Github class="mr-2 h-4 w-4" />
<span>GitHub Repository</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem>
<LifeBuoy class="mr-2 h-4 w-4" />
<span>Support</span>
</BrDropdownMenuItem>
<BrDropdownMenuItem disabled>
<Cloud class="mr-2 h-4 w-4" />
<span>API Service (Under Maintenance)</span>
</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem shortcut="⇧⌘Q" class="text-destructive focus:bg-destructive focus:text-destructive-foreground">
<LogOut class="mr-2 h-4 w-4" />
<span>Logout</span>
</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</template>#嵌套子菜单与快捷键
支持多级嵌套子菜单,以及通过 shortcut 属性配置快捷键。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrDropdownMenuSeparator,
BrDropdownMenuSub,
BrDropdownMenuSubTrigger,
BrDropdownMenuSubContent,
BrButton
} from '@breezeui/vue'
</script>
<template>
<BrDropdownMenu>
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline">User Action</BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent class="w-56">
<BrDropdownMenuItem shortcut="⇧⌘P">Profile Page</BrDropdownMenuItem>
<BrDropdownMenuItem shortcut="⌘B">Billing</BrDropdownMenuItem>
<BrDropdownMenuItem shortcut="⌘S">Settings</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuSub>
<BrDropdownMenuSubTrigger>Invite User</BrDropdownMenuSubTrigger>
<BrDropdownMenuSubContent>
<BrDropdownMenuItem>Via Email</BrDropdownMenuItem>
<BrDropdownMenuItem>Via SMS</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem>More Options...</BrDropdownMenuItem>
</BrDropdownMenuSubContent>
</BrDropdownMenuSub>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem shortcut="⇧⌘Q" disabled>Logout</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</template>#自定义触发方式(悬浮/右键)
支持 click、hover、contextmenu 触发方式,可通过 trigger 属性配置。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrDropdownMenuSeparator,
BrButton
} from '@breezeui/vue'
</script>
<template>
<div class="flex gap-4">
<!-- Hover Trigger -->
<BrDropdownMenu trigger="hover">
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline">Hover to expand</BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent>
<BrDropdownMenuItem>Option 1</BrDropdownMenuItem>
<BrDropdownMenuItem>Option 2</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
<!-- Right-click Trigger -->
<BrDropdownMenu trigger="contextmenu">
<BrDropdownMenuTrigger as-child>
<div class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
Right-click in this area
</div>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent>
<BrDropdownMenuItem>Refresh</BrDropdownMenuItem>
<BrDropdownMenuItem>Save As...</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem class="text-destructive">Delete</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</div>
</template>#与表单集成
在表单操作或表格行操作中的典型应用。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrDropdownMenuSeparator,
BrButton,
BrForm,
BrFormItem
} from '@breezeui/vue'
import { ChevronDown } from 'lucide-vue-next'
</script>
<template>
<BrForm>
<BrFormItem label="Action">
<BrDropdownMenu>
<BrDropdownMenuTrigger as-child>
<BrButton variant="outline">Action <ChevronDown class="ml-2 h-4 w-4" /></BrButton>
</BrDropdownMenuTrigger>
<BrDropdownMenuContent>
<BrDropdownMenuItem>Edit</BrDropdownMenuItem>
<BrDropdownMenuItem>Copy</BrDropdownMenuItem>
<BrDropdownMenuSeparator />
<BrDropdownMenuItem class="text-destructive">Delete</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</BrFormItem>
</BrForm>
</template>#主题定制
结合 BrConfigProvider,可以全局覆盖组件默认样式,例如修改圆角、悬浮态颜色、菜单阴影等。同时可以通过 TailwindCSS 局部覆盖样式。
<script setup lang="ts">
import {
BrDropdownMenu,
BrDropdownMenuTrigger,
BrDropdownMenuContent,
BrDropdownMenuItem,
BrButton,
BrConfigProvider
} from '@breezeui/vue'
</script>
<template>
<BrConfigProvider
:theme="{
light: {
radius: '1rem',
primary: '220 90% 56%',
popover: '0 0% 100%',
'popover-foreground': '240 10% 3.9%',
},
dark: {
radius: '1rem',
primary: '220 90% 56%',
popover: '240 10% 3.9%',
'popover-foreground': '0 0% 98%',
}
}"
>
<BrDropdownMenu>
<BrDropdownMenuTrigger as-child>
<BrButton>Custom Theme Dropdown Menu</BrButton>
</BrDropdownMenuTrigger>
<!-- Local Override Style Example -->
<BrDropdownMenuContent class="border-primary/20 shadow-xl">
<BrDropdownMenuItem class="focus:bg-primary focus:text-primary-foreground">
Highlight Option
</BrDropdownMenuItem>
<BrDropdownMenuItem>Normal Option</BrDropdownMenuItem>
</BrDropdownMenuContent>
</BrDropdownMenu>
</BrConfigProvider>
</template>#API 说明
#BrDropdownMenu
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| open (v-model) | boolean | - | 控制菜单是否展开 |
| defaultOpen | boolean | false | 默认展开状态 |
| dir | 'ltr' | 'rtl' | 'ltr' | 文本阅读方向 |
| trigger | 'click' | 'hover' | 'contextmenu' | Array | 'click' | 触发方式配置 |
| openDelay | number | 200 | 悬浮触发时的展开延迟(ms) |
| closeDelay | number | 300 | 悬浮触发时的收起延迟(ms) |
#BrDropdownMenuContent
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| class | any | - | 自定义类名 |
| side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | 菜单弹出的方向 |
| sideOffset | number | 4 | 菜单距离触发器的偏移量 |
| align | 'start' | 'center' | 'end' | 'center' | 菜单对齐方式 |
| alignOffset | number | 0 | 对齐偏移量 |
#BrDropdownMenuItem
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| disabled | boolean | false | 是否禁用 |
| shortcut | string | - | 快捷键文本(如 "⌘K") |
| inset | boolean | false | 是否包含左侧缩进(用于对齐图标) |
#BrDropdownMenuSub
用于嵌套子菜单的根容器,无需额外配置属性。
#BrDropdownMenuEmpty / BrDropdownMenuLoading
用于展示空状态或加载中状态。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| text | string | 'No data' / 'Loading...' | 提示文本 |