motif svelteArc

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.

Live specimen

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.

Installation

pnpm dlx shadcn-svelte@latest add @arcui/popover

Usage

<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

PropTypeDefaultDescription
open (Popover)booleanfalseControlled open state. Use bind:open for two-way reactivity with Svelte 5 runes.
defaultOpen (Popover)booleanfalseInitial 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)number6Distance in pixels between the trigger and the floating panel.
collisionPadding (PopoverContent)number10Minimum 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

KeyAction
Enter / SpaceOpens the popover when focused on the trigger.
EscapeCloses the popover and restores focus to the trigger.
TabCycles 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