Usage
Popover의 기본 슬롯에 [Button](/docs/components/buttonxph04x 또는 다른 구성 요소를 사용합니다.
그런 다음 #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 모드
mode 소품을 사용하여 Popover의 모드를 변경합니다. 기본값은 click입니다.
hover 모드에서는 enable-touch prop을 설정하여 사용자가 터치 장치에서 트리거를 탭하여 Popover를 토글하거나 탭할 트리거에 click 모드를 사용하도록 합니다.<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>Delay
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 파일
content prop을 사용하여 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 화살표
arrow Prop을 사용하여 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 모델
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 키를 누를 때 Popover가 허용되지 않도록 제어합니다. 기본값은 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>
examples 예제
Control 오픈 상태
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>
<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를 사용하여 Popover를 토글할 수 있습니다:kbd{value="O"}.With 명령어 팔레트
Popover의 콘텐츠에 CommandPalette 구성 요소를 사용할 수 있습니다.
<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>
다음 커서
reference 소품을 사용하여 포인터를 요소 위에 놓을 때 포인터를 따라 이동하도록 할 수 있습니다.
<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>
앵커 슬롯 포함
#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-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 파일
Props (### Props)
| 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; } |
슬롯
| Slot | Type |
|---|---|
default | { open: boolean; } |
content | SlotProps<M> |
anchor | SlotProps<M> |
Popover에 대해 노출되지만 HoverCard에 대해서는 노출되지 않기 때문에 mode가 click로 설정된 경우에만 close 함수를 사용할 수 있습니다.Emits 파일
| Event | Type |
|---|---|
close:prevent | [] |
update:open | [value: boolean] |
Theme 테마
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'
}
}
}
})
]
})