Popover
Import
import { Popover, PopoverContent, PopoverTrigger } from "@dr-max/ui/popover"
The entry carries its own precompiled CSS — no extra style imports needed.
Usage
The popover is composed of three parts: Popover holds the open state, PopoverTrigger toggles it, and PopoverContent is the floating panel rendered in a portal. Pass as-child to the trigger to use your own element — typically a Button — instead of the default plain button. Click the trigger below to open it:
<script setup lang="ts">
import { Button } from "@dr-max/ui/button"
import { Popover, PopoverContent, PopoverTrigger } from "@dr-max/ui/popover"
</script>
<template>
<Popover>
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent>
There are a lot of things you can do in space, and space essentially is
unlimited resources.
</PopoverContent>
</Popover>
</template>
Side and align
The panel opens on side="top" centered on the trigger by default. Use side (top, right, bottom, left) and align (start, center, end) on PopoverContent to place it elsewhere — it flips automatically when there is not enough space:
<template>
<Popover>
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent side="bottom" align="start">
Opens below the trigger, aligned to its left edge.
</PopoverContent>
</Popover>
</template>
Offsets
side-offset sets the distance in px between the trigger and the panel (default 8); align-offset nudges the panel in px from its start/end alignment:
<template>
<PopoverContent side="bottom" align="start" :side-offset="12" :align-offset="-4">
…
</PopoverContent>
</template>
Without arrow
Set :arrow="false" on PopoverContent to hide the arrow pointing at the trigger:
<template>
<Popover>
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent :arrow="false">
There are a lot of things you can do in space, and space essentially is
unlimited resources.
</PopoverContent>
</Popover>
</template>
Open by default
Use default-open on Popover to render the popover open while keeping it uncontrolled:
<template>
<Popover default-open>
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent>…</PopoverContent>
</Popover>
</template>
Controlled state
Bind the open state with v-model:open when the consumer needs to own it (e.g. closing the popover from a button inside the panel):
<script setup lang="ts">
import { Button } from "@dr-max/ui/button"
import { Popover, PopoverContent, PopoverTrigger } from "@dr-max/ui/popover"
import { ref } from "vue"
const open = ref(false)
</script>
<template>
<Popover v-model:open="open">
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent>
<Button variant="naked" @click="open = false">Close</Button>
</PopoverContent>
</Popover>
</template>
Modal
Set modal on Popover to disable interaction with outside elements while the popover is open:
<template>
<Popover modal>
…
</Popover>
</template>
Playground
<script setup lang="ts">
import { Button } from '@dr-max/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@dr-max/ui/popover'
</script>
<template>
<Popover>
<PopoverTrigger as-child>
<Button variant="secondary">Open popover</Button>
</PopoverTrigger>
<PopoverContent side="top" align="center" :side-offset="8" arrow>There are a lot of things you can do in space, and space essentially is unlimited resources.</PopoverContent>
</Popover>
</template>