Popover ported
A small anchored surface for contextual information.
A floating panel anchored to a trigger, with spring settle, origin-aware scale, and collision-aware viewport flipping.
Loading demo…
Guidance
When to use
- Click-opened panels with interactive content, like share settings or a small filter form.
- Non-modal helpers that should stay open while people interact with the rest of the page.
- Custom pickers built from your own controls anchored to a button.
When not to use
- Use Tooltip for short hover labels.
- Use Hover Card for read-only previews that open on hover.
- Use Dialog when the choice must block the page, and Dropdown Menu for a list of commands.
pnpm dlx shadcn-svelte@latest add @arcui/popoverUsage
<script lang="ts">
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverClose
} from '$lib/components/popover';
let open = $state(false);
</script>
<Popover bind:open>
<PopoverTrigger class="demo-trigger">Share settings</PopoverTrigger>
<PopoverContent>
<div style="font-weight: 600; margin-bottom: var(--space-1); font-size: var(--text-sm);">Share this project</div>
<p class="demo-pop-text">Anyone with the link can view.</p>
<PopoverClose class="demo-close">Done</PopoverClose>
</PopoverContent>
</Popover>Variants & Examples
Default Controlled
Two-way binding via bind:open with trigger and close buttons.
<Popover bind:open>
<PopoverTrigger class="demo-trigger">Open popover</PopoverTrigger>
<PopoverContent>
<p>Anchored floating panel.</p>
<PopoverClose class="demo-close">Close</PopoverClose>
</PopoverContent>
</Popover>Centered Alignment with Custom Offset
Centers the floating panel relative to the trigger and increases the sideOffset distance.
<Popover>
<PopoverTrigger class="demo-trigger">Centered Popover</PopoverTrigger>
<PopoverContent align="center" sideOffset={12}>
<p>Positioned center with 12px offset.</p>
</PopoverContent>
</Popover>Custom Placement (Top Side)
Renders the panel above the trigger with collision-aware viewport flipping.
<Popover>
<PopoverTrigger class="demo-trigger">Top Aligned</PopoverTrigger>
<PopoverContent side="top" align="start">
<p>Appears above the trigger with collision handling.</p>
</PopoverContent>
</Popover>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
open (Popover) | boolean | false | Controlled open state. Use bind:open for two-way reactivity with Svelte 5 runes. |
defaultOpen (Popover) | boolean | false | Initial open state when uncontrolled. |
onOpenChange (Popover) | (open: boolean) => void | — | Callback fired whenever the popover opens or closes. |
onOpenChangeComplete (Popover) | (open: boolean) => void | — | Callback fired when the open or close animation completes. |
align (PopoverContent) | 'start' | 'center' | 'end' | 'start' | Alignment of the floating content along the trigger edge. |
side (PopoverContent) | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Preferred placement side relative to the trigger. |
sideOffset (PopoverContent) | number | 6 | Distance in pixels between the trigger and the floating panel. |
collisionPadding (PopoverContent) | number | 10 | Minimum distance in pixels from the viewport edges to prevent clipping. |
ref (PopoverTrigger / Content / Close) | HTMLElement | null | — | Bindable ref to the underlying DOM element. |
Keyboard Interactions
| Key | Action |
|---|---|
Enter / Space | Opens the popover when focused on the trigger. |
Escape | Closes the popover and restores focus to the trigger. |
Tab | Cycles focus through interactive elements inside the open popover. |
Accessibility
- Bits UI automatically sets aria-expanded, aria-controls, and aria-haspopup="dialog" on PopoverTrigger.
- Focus automatically moves into the popover content upon opening and returns smoothly to the trigger on close.
- Dismissible via Escape key press or clicking outside the floating surface.
- Popover is non-modal by default, allowing seamless interaction with the rest of the page; set modal={true} to trap focus when needed.
- High-contrast focus ring outlines interactive elements in compliance with WCAG 2.1 AA standards.
Motion
CSS transitions: the panel fades and settles from 5px toward its trigger at 0.97 scale on a spring; it leaves in 140ms. Transitions are used instead of keyframes, so a reopen mid-close reverses smoothly from where the panel currently is. Reduced motion drops the translate transform and keeps an instantaneous opacity fade.
Notes for AI
- Use for click-opened panels containing interactive elements (forms, share menus, multi-step actions). Use Tooltip for hover-only readouts.
- Compose using Popover, PopoverTrigger, PopoverContent, and optional PopoverClose.
- Always prefer bind:open for reactive state synchronization in Svelte 5.
- PopoverContent automatically renders inside a portal at the document body to prevent overflow clipping.
Source of truth: registry/components/popover/popover.tsx