Popover
A floating content panel anchored to a trigger element. Supports controlled and uncontrolled usage, 4 placements, keyboard dismiss, and outside-click close.
Basic
Pass a trigger prop (React) or use the #trigger slot (Vue).
The popover opens on click and closes on outside click or Escape.
import { Popover, Button } from "@usevyre/react";
const [open, setOpen] = useState(false);
<Popover
open={open}
onOpenChange={setOpen}
trigger={<Button variant="secondary">Open Popover</Button>}
>
<p>Popover content goes here.</p>
<Button size="sm" variant="ghost" onClick={() => setOpen(false)}>Close</Button>
</Popover> <script setup>
import { Popover, Button } from "@usevyre/vue";
const open = ref(false);
</script>
<template>
<Popover v-model="open">
<template #trigger>
<Button variant="secondary">Open Popover</Button>
</template>
<p>Popover content goes here.</p>
<Button size="sm" variant="ghost" @click="open = false">Close</Button>
</Popover>
</template> Uncontrolled
Omit open / onOpenChange (React) or v-model (Vue)
to let the popover manage its own open state.
{/* Omit open/onOpenChange for uncontrolled (toggle managed internally) */}
<Popover trigger={<Button variant="ghost">Info</Button>}>
<p>Uncontrolled popover — no state needed.</p>
</Popover> <Popover>
<template #trigger>
<Button variant="ghost">Info</Button>
</template>
<p>Uncontrolled popover — no v-model needed.</p>
</Popover> Placement
12 placement options: 4 sides × 3 alignments (start, center, end).
Positions are computed in JS so the popover always appears on the correct side of the trigger.
{/* Side only — defaults to center alignment */}
<Popover placement="top" trigger={<Button>Top</Button>}>...</Popover>
<Popover placement="bottom" trigger={<Button>Bottom</Button>}>...</Popover>
<Popover placement="left" trigger={<Button>Left</Button>}>...</Popover>
<Popover placement="right" trigger={<Button>Right</Button>}>...</Popover>
{/* Side + alignment */}
<Popover placement="top-start" trigger={<Button>top-start</Button>}>...</Popover>
<Popover placement="bottom-end" trigger={<Button>bottom-end</Button>}>...</Popover>
<Popover placement="right-start" trigger={<Button>right-start</Button>}>...</Popover> <Popover placement="top">
<template #trigger><Button size="sm">Top</Button></template>
...
</Popover> Props
Props
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | ReactElement | — | (React) The anchor element. Passed as a prop. |
#trigger slot | slot | — | (Vue) The anchor element. Use the named slot. |
open | boolean | — | Controlled open state. Omit for uncontrolled. |
onOpenChange / v-model | (open: boolean) => void | — | Called when open state changes. |
placement | "top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end" | "right" | "right-start" | "right-end" | "bottom" | Side and alignment of the popover relative to the trigger. |
closeOnOutside | boolean | true | Close when clicking outside the popover. |
class / className | string | — | Additional CSS class on the popover panel. |
Valid props
| Prop | Values | Default |
|---|---|---|
placement | "top"|"top-start"|"top-end"|"bottom"|"bottom-start"|"bottom-end"|"left"|"left-start"|"left-end"|"right"|"right-start"|"right-end" | bottom |
open | true|false | false |
closeOnOutside | true|false | true |
Common AI mistakes
- placement="top-center"→ Use placement="top" for centered placement
Quick examples
Popover with custom content
<Popover trigger={<Button variant="secondary">More info</Button>} placement="bottom-start">
<div style={{ padding: 'var(--vyre-spacing-4)' }}>
<p>Detailed information here.</p>
</div>
</Popover>