在 Popover 的默认插槽中使用按钮或任何其他组件。
然后,使用#content插槽添加 Popover 打开时显示的内容。
<template>
<UPopover>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
使用mode属性来改变 Popover 的模式。默认为click。
<template>
<UPopover mode="hover">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
当使用hover模式时,可以使用open-delay和close-delay属性来控制 Popover 打开或关闭前的延迟。
<template>
<UPopover mode="hover" :open-delay="500" :close-delay="300">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
使用content属性来控制 Popover 内容的渲染方式,例如它的align或side。
<template>
<UPopover
:content="{
align: 'center',
side: 'bottom',
sideOffset: 8
}"
>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
使用arrow属性在 Popover 上显示一个箭头。
<template>
<UPopover arrow>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
使用modal属性来控制 Popover 是否阻止与外部内容的交互。默认为false。
<template>
<UPopover modal>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
使用dismissible属性来控制 Popover 是否可以通过点击外部或按 Esc 键关闭。默认为true。
close:prevent事件。<template>
<UPopover :dismissible="false" :ui="{ content: 'p-4' }">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content="{ close }">
<div class="flex items-center gap-4 mb-4">
<h2 class="text-highlighted font-semibold">
Popover non-dismissible
</h2>
<UButton color="neutral" variant="ghost" icon="i-lucide-x" @click="close" />
</div>
<Placeholder class="size-full min-h-48" />
</template>
</UPopover>
</template>
您可以通过使用default-open prop 或v-model:open指令来控制打开状态。
<script setup lang="ts">
const open = ref(false)
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<UPopover v-model:open="open">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>
defineShortcuts,您可以通过按O来切换 Popover。您可以在 Popover 的内容中包含命令面板组件。
<script setup lang="ts">
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error' as const
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success' as const
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info' as const
}
}
])
const label = ref([])
</script>
<template>
<UPopover :content="{ side: 'right', align: 'start' }">
<UButton
icon="i-lucide-tag"
label="Select labels"
color="neutral"
variant="subtle"
/>
<template #content>
<UCommandPalette
v-model="label"
multiple
placeholder="Search labels..."
:groups="[{ id: 'labels', items }]"
:ui="{ input: '[&>input]:h-8 [&>input]:text-sm' }"
/>
</template>
</UPopover>
</template>
您可以通过使用以下方式使 Popover 在悬停于元素时跟随光标参考属性
<script setup lang="ts">
const open = ref(false)
const anchor = ref({ x: 0, y: 0 })
const reference = computed(() => ({
getBoundingClientRect: () =>
({
width: 0,
height: 0,
left: anchor.value.x,
right: anchor.value.x,
top: anchor.value.y,
bottom: anchor.value.y,
...anchor.value
} as DOMRect)
}))
</script>
<template>
<UPopover
:open="open"
:reference="reference"
:content="{ side: 'top', sideOffset: 16, updatePositionStrategy: 'always' }"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
@pointerenter="open = true"
@pointerleave="open = false"
@pointermove="(ev) => {
anchor.x = ev.clientX
anchor.y = ev.clientY
}"
>
Hover me
</div>
<template #content>
<div class="p-4">
{{ anchor.x.toFixed(0) }} - {{ anchor.y.toFixed(0) }}
</div>
</template>
</UPopover>
</template>
您可以使用#anchor插槽将 Popover 定位到自定义元素。
mode设置为click时才有效。<script lang="ts" setup>
const open = ref(false)
</script>
<template>
<UPopover
v-model:open="open"
:dismissible="false"
:ui="{ content: 'w-(--reka-popper-anchor-width) p-4' }"
>
<template #anchor>
<UInput placeholder="Focus to open" @focus="open = true" @blur="open = false" />
</template>
<template #content>
<Placeholder class="w-full aspect-square" />
</template>
</UPopover>
</template>
| 属性 | 默认值 | 类型 |
|---|---|---|
mode | 'click' | "click" | "hover"弹出框的显示模式。 |
内容 | { 侧面: '底部', 侧面偏移量: 8, 碰撞填充: 8 } | PopoverContentProps & Partial<EmitsToProps<PopoverContentImplEmits>>弹出框的内容。
|
arrow | false | boolean | PopoverArrowProps在弹出框旁边显示一个箭头。 |
portal | true | string | false | true | HTMLElement在传送门中渲染弹出框。 |
参考 | 元素 | 虚拟元素用于定位的引用(或锚点)元素。 如果未提供,将使用当前组件作为锚点。
| |
可关闭的 | true | boolean当 |
defaultOpen | boolean弹出框最初渲染时的打开状态。当您不需要控制其打开状态时使用。 | |
open | boolean弹出框的受控打开状态。 | |
modal | false | boolean弹出框的模态。当设置为 true 时,与外部元素的交互将被禁用,并且屏幕阅读器将只能看到弹出框内容。 |
打开延迟 | 0 | number鼠标进入触发器到悬停卡片打开的持续时间。 |
关闭延迟 | 0 | number鼠标离开触发器或内容到悬停卡片关闭的持续时间。 |
ui | { content?: ClassNameValue; arrow?: ClassNameValue; } |
| 插槽 | 类型 |
|---|---|
default | { open: boolean; } |
内容 | { close: () => void; } |
锚点 | { close: () => void; } |
| 事件 | 类型 |
|---|---|
close:prevent | [] |
update:open | [value: boolean] |
export default defineAppConfig({
ui: {
popover: {
slots: {
content: 'bg-default shadow-lg rounded-md ring ring-default data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-popover-content-transform-origin) focus:outline-none pointer-events-auto',
arrow: 'fill-default'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
popover: {
slots: {
content: 'bg-default shadow-lg rounded-md ring ring-default data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-popover-content-transform-origin) focus:outline-none pointer-events-auto',
arrow: 'fill-default'
}
}
}
})
]
})