#Popover 悬浮弹窗
当元素获取焦点、鼠标悬浮或点击时,弹出显示相关信息的浮层。基于 BrConfigProvider 实现全局主题配置,支持多触发方式、自适应定位。
#组件特性
- 🛠️ 多方向弹出:支持上下左右及其对齐偏移共 12 种方向,自动适应屏幕边缘。
- 🖱️ 多种触发方式:支持点击、悬浮、聚焦等多种触发方式。
- 🎨 主题定制:支持基于
BrConfigProvider的全局主题定制,以及基于 TailwindCSS 的局部样式覆盖。
#基础用法
最基础的悬浮弹窗展示,通过点击触发。
<script setup lang="ts">
import {
BrPopover,
BrPopoverTrigger,
BrPopoverContent,
BrPopoverArrow,
BrPopoverClose,
BrButton,
BrInput
} from '@breezeui/vue'
</script>
<template>
<BrPopover>
<BrPopoverTrigger as-child>
<BrButton variant="outline">Open Popover</BrButton>
</BrPopoverTrigger>
<BrPopoverContent
placement="bottom"
:side-offset="4"
class="w-80"
@open-auto-focus="(e: Event) => e.preventDefault()"
>
<div class="space-y-2">
<h4 class="font-medium leading-none">Dimensions</h4>
<p class="text-sm text-muted-foreground">Set the dimensions for the layer.</p>
<div class="grid gap-2 pt-4">
<div class="grid grid-cols-3 items-center gap-4">
<label for="width" class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Width</label>
<BrInput id="width" model-value="100%" class="col-span-2 h-8" />
</div>
<div class="grid grid-cols-3 items-center gap-4">
<label for="height" class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Height</label>
<BrInput id="height" model-value="25px" class="col-span-2 h-8" />
</div>
</div>
</div>
<BrPopoverArrow class="fill-popover" />
<BrPopoverClose class="absolute top-2 right-2 text-muted-foreground hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
</BrPopoverClose>
</BrPopoverContent>
</BrPopover>
</template>#弹出位置
支持 placement 属性控制弹出位置,支持 12 种不同的方向。
<script setup lang="ts">
import {
BrPopover,
BrPopoverTrigger,
BrPopoverContent,
BrPopoverArrow,
BrButton
} from '@breezeui/vue'
const positions = [
'top-start',
'top',
'top-end',
'right-start',
'right',
'right-end',
'bottom-start',
'bottom',
'bottom-end',
'left-start',
'left',
'left-end'
] as const
</script>
<template>
<div class="flex flex-wrap gap-4 py-8 max-w-3xl justify-center mx-auto">
<BrPopover v-for="pos in positions" :key="pos">
<BrPopoverTrigger as-child>
<BrButton variant="outline" class="w-28 text-xs">{{ pos }}</BrButton>
</BrPopoverTrigger>
<BrPopoverContent :placement="pos" class="w-auto p-4">
<div class="text-sm font-medium">Placement: <span class="text-primary">{{ pos }}</span></div>
<BrPopoverArrow class="fill-popover" />
</BrPopoverContent>
</BrPopover>
</div>
</template>#自定义触发方式
支持 click、hover 和 focus 触发方式,可通过 trigger 属性进行配置。
<script setup lang="ts">
import { ref } from 'vue'
import {
BrPopover,
BrPopoverTrigger,
BrPopoverContent,
BrPopoverArrow,
BrButton,
BrInput
} from '@breezeui/vue'
const inputValue = ref('')
</script>
<template>
<div class="flex gap-8 flex-col sm:flex-row items-start sm:items-center">
<!-- Hover Trigger -->
<BrPopover trigger="hover" :open-delay="100">
<BrPopoverTrigger as-child>
<span class="underline decoration-dashed underline-offset-4 cursor-help text-sm font-medium">
Hover over me
</span>
</BrPopoverTrigger>
<BrPopoverContent placement="top" class="w-64 p-3">
<div class="text-sm">
<strong>BreezeUI</strong> is a modern UI library based on TailwindCSS and Vue 3.
</div>
<BrPopoverArrow class="fill-popover" />
</BrPopoverContent>
</BrPopover>
<!-- Focus Trigger -->
<BrPopover trigger="focus">
<BrPopoverTrigger as-child>
<BrInput v-model="inputValue" placeholder="Focus me..." class="w-64" />
</BrPopoverTrigger>
<BrPopoverContent placement="bottom-start" class="w-64 p-3">
<div class="text-sm text-muted-foreground">
Password must be at least 8 characters long and contain a number.
</div>
<BrPopoverArrow class="fill-popover" />
</BrPopoverContent>
</BrPopover>
</div>
</template>#主题定制
结合 BrConfigProvider 可以全局覆盖组件的默认样式,也可以通过 TailwindCSS 局部覆盖样式。
<script setup lang="ts">
import {
BrPopover,
BrPopoverTrigger,
BrPopoverContent,
BrButton,
BrConfigProvider
} from '@breezeui/vue'
</script>
<template>
<BrConfigProvider
:theme="{
light: {
radius: '1rem',
popover: '220 14% 96%',
'popover-foreground': '240 10% 3.9%',
},
dark: {
radius: '1rem',
popover: '240 10% 15%',
'popover-foreground': '0 0% 98%',
}
}"
>
<BrPopover>
<BrPopoverTrigger as-child>
<BrButton>Custom Theme Popover</BrButton>
</BrPopoverTrigger>
<!-- Local override example -->
<BrPopoverContent class="border-primary/20 shadow-xl p-6">
<h4 class="font-medium mb-2">Global Theme Customization</h4>
<p class="text-sm text-muted-foreground">
This popover uses custom border radius and background color via BrConfigProvider.
</p>
</BrPopoverContent>
</BrPopover>
</BrConfigProvider>
</template>#加载与空状态
支持在弹窗内容中展示加载中 loading 和空数据 empty 状态。
<script setup lang="ts">
import {
BrPopover,
BrPopoverTrigger,
BrPopoverContent,
BrButton
} from '@breezeui/vue'
</script>
<template>
<div class="flex gap-4">
<BrPopover>
<BrPopoverTrigger as-child>
<BrButton variant="outline">Loading State</BrButton>
</BrPopoverTrigger>
<BrPopoverContent loading placement="bottom" />
</BrPopover>
<BrPopover>
<BrPopoverTrigger as-child>
<BrButton variant="outline">Empty State</BrButton>
</BrPopoverTrigger>
<BrPopoverContent empty placement="bottom" />
</BrPopover>
</div>
</template>#API 参考
#BrPopover
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
open (v-model) | boolean | - | 受控模式下,弹窗的展开状态 |
defaultOpen | boolean | false | 非受控模式下,弹窗的默认展开状态 |
trigger | 'click' | 'hover' | 'focus' | 'manual' | 'click' | 触发方式 |
disabled | boolean | false | 是否禁用触发器 |
openDelay | number | 200 | 悬浮触发时的展开延迟(毫秒) |
closeDelay | number | 300 | 悬浮触发时的收起延迟(毫秒) |
#BrPopoverContent
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
placement | 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end' | 'bottom' | 弹窗出现的位置 |
sideOffset | number | 4 | 弹窗距离触发元素的偏移量 |
mask | boolean | false | 是否展示背景遮罩 |
loading | boolean | false | 是否处于加载态 |
empty | boolean | false | 是否为空内容态 |
closeStrategy | Array<'click-outside' | 'escape' | 'scroll'> | ['click-outside', 'escape'] | 触发关闭的策略。可配置滚动时关闭 ('scroll') |
#BrPopoverTrigger
无特殊属性,通过 as-child 可以将事件委托给子元素(推荐使用)。
#BrPopoverArrow
继承自 Radix Vue 的 PopoverArrow,可直接传递 class 进行样式覆盖(如 fill-popover 控制箭头颜色)。
#BrPopoverClose
无特殊属性,用于包裹关闭弹窗的按钮,通过 as-child 可以将点击事件委托给子元素。