Popover
Bearbeiten
Verwenden Sie einen Button oder eine andere Komponente im Standard-Steckplatz des Popovers.
Verwenden Sie dann den #content-Steckplatz, um den Inhalt hinzuzufügen, der angezeigt wird, wenn das Popover geöffnet ist.
<template>
<UPopover>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>Mode ist
Verwenden Sie die mode-prop, um den Modus des Popover. Defaults auf click zu ändern.
hover-Modus die enable-touch-Prop so ein, dass Benutzer den Popover durch Antippen des Auslösers auf Touch-Geräten umschalten können, oder verwenden Sie den click-Modus für Trigger, die angetippt werden sollen.<template>
<UPopover mode="hover" enable-touch>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>hover-Modus verwenden, wird anstelle der Komponente Popover die Reka-Benutzeroberfläche xph0444x verwendet.Delay
Wenn Sie den hover-Modus verwenden, können Sie die open-delay-und close-delay-Props verwenden, um die Verzögerung zu steuern, bevor der Popover geöffnet oder geschlossen wird.
<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>Inhalt
Verwenden Sie die content-Prop, um zu steuern, wie der Popover-Inhalt gerendert wird, z. B. align oder 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 Bearbeiten
Verwenden Sie die arrow-Prop, um einen Pfeil auf dem Popover anzuzeigen.
<template>
<UPopover arrow>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>Modal ist
Verwenden Sie die modal-prop, um zu steuern, ob der Popover die Interaktion mit externen Inhalten blockiert.
<template>
<UPopover modal>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="size-48 m-4 inline-flex" />
</template>
</UPopover>
</template>Dismissible (nicht zulässig)
Verwenden Sie die dismissible-Prop, um zu steuern, ob der Popover deaktiviert werden kann, wenn Sie außerhalb des Popovers klicken oder escape drücken.
close:prevent-Ereignis wird ausgelöst, wenn der Benutzer versucht, es zu schließen.<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>
Beispiele
Control im offenen Zustand
Sie können den offenen Zustand mit der Direktive default-open prop oder der Direktive v-model:open steuern.
<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>
<script setup lang="ts">
import { ref } from 'vue'
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 das Popover umschalten, indem Sie: kbd{value="O"}.Mit Befehlspalette
Sie können eine CommandPalette-Komponente innerhalb des Popover-Inhalts verwenden.
<script setup lang="ts">
import type { CommandPaletteItem } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
}
}
] satisfies CommandPaletteItem[])
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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteItem } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
}
}
] satisfies CommandPaletteItem[])
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>
Mit folgendem Cursor
Sie können den Popover dazu bringen, dem Cursor zu folgen, wenn Sie mit der Prop reference über ein Element fahren:
<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: PointerEvent) => {
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>
<script setup lang="ts">
import { ref, computed } from 'vue'
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: PointerEvent) => {
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>
Mit Anchor-Slot
Sie können den #anchor-Steckplatz verwenden, um das Popover gegen ein benutzerdefiniertes Element zu positionieren.
modeclick ist.<script lang="ts" setup>
const open = ref(false)
</script>
<template>
<UPopover
v-model:open="open"
:dismissible="false"
:ui="{ content: 'w-(--reka-popover-trigger-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>
API Bearbeiten
Props (englisch)
| Prop | Default | Type |
|---|---|---|
mode | 'click' | MThe display mode of the popover. |
content | { side: 'bottom', sideOffset: 8, collisionPadding: 8 } | PopoverContentProps & Partial<EmitsToProps<PopoverContentImplEmits>>The content of the popover. |
arrow | false | boolean | PopoverArrowProps Display an arrow alongside the popover.
|
portal | true | string | false | true | HTMLElementRender the popover in a portal. |
reference | Element | VirtualElementThe reference (or anchor) element that is being referred to for positioning. Accepts an element or a virtual element (anything with | |
dismissible | true | boolean When |
defaultOpen | boolean The open state of the popover when it is initially rendered. Use when you do not need to control its open state. | |
open | boolean The controlled open state of the popover. | |
modal | false | boolean The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers. |
openDelay | 0 | numberThe duration from when the mouse enters the trigger until the hover card opens. |
closeDelay | 0 | numberThe duration from when the mouse leaves the trigger or content until the hover card closes. |
enableTouch | boolean When | |
ui | { content?: SlotClass; arrow?: SlotClass; } |
Slots (englisch)
| Slot | Type |
|---|---|
default | { open: boolean; } |
content | SlotProps<M> |
anchor | SlotProps<M> |
close-Funktion ist nur verfügbar, wenn mode auf click gesetzt ist, da die Reka-Benutzeroberfläche dies für Popover, nicht jedoch für HoverCard verfügbar macht.Emits (englisch)
| Event | Type |
|---|---|
close:prevent | [] |
update:open | [value: boolean] |
Theme Bearbeiten
export default defineAppConfig({
ui: {
popover: {
slots: {
content: 'bg-default shadow-lg rounded-md ring ring-default data-[state=open]:animate-[scale-in_100ms_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-popover-content-transform-origin) focus:outline-none pointer-events-auto',
arrow: 'fill-bg stroke-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_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-popover-content-transform-origin) focus:outline-none pointer-events-auto',
arrow: 'fill-bg stroke-default'
}
}
}
})
]
})