Overlays

Popover

Anchored floating panel positioned by Floating UI that hosts non-modal contextual content beside a trigger element.

import { Popover } from '@lostgradient/cinder/popover';
overlayfloating
01

Overview

Non-blocking floating panel anchored to a trigger element for contextual content.

Usage

svelte
<script lang="ts">
  import { Button } from '@lostgradient/cinder/button';
  import { Popover } from '@lostgradient/cinder/popover';

  let open = $state(false);
  const headingId = 'my-popover-title';
</script>

<Popover bind:open ariaLabelledby={headingId} arrowVisible focusManagement="preserve">
  {#snippet trigger()}
    <Button label="Open" onclick={() => (open = !open)} />
  {/snippet}

  <h2 id={headingId}>Panel heading</h2>
  <p>Panel content goes here.</p>
</Popover>

Choosing this component

Use Popover for rich, interactive contextual content anchored to a trigger — help panels, color pickers, settings cards, and similar surfaces that do not need to interrupt the user.

Situation Reach for
Short descriptive hint shown on hover or focus Tooltip
A list of navigable actions triggered from a button Dropdown (sets role="menu", manages arrow-key navigation)
A combo-box, tag picker, or filterable option list Combobox (manages listbox role, keyboard selection, filtering)
Rich content, settings, or any non-menu panel Popover
Focused task that should block the rest of the page Modal, Drawer, or Sheet

focusManagement"panel" vs "preserve"

  • "panel" (default): Focus moves to the first focusable element inside the panel when it opens. Use this when the panel contains a form field or search input that needs immediate keyboard access (date pickers, filter panels, inline editors).
  • "preserve": Focus stays on the trigger after the panel opens. Use this for content-first panels (account settings, help text, status details) where the user is reading, not immediately interacting.
Live preview
02

When to use

Use when
  • Showing rich, interactive contextual content anchored to a trigger such as a help panel, color picker, or listbox surface.
  • Presenting non-blocking supplementary controls that should dismiss on outside click or Escape.
Avoid when
  • Showing a short descriptive hint on hover or focus — use tooltip instead.
  • Interrupting the user for a focused task — use modal, drawer, or sheet so the surface is modal.
03

Examples

Basic popover

A button trigger that opens a floating panel. The panel preserves focus on the trigger — use focusManagement="panel" when the panel contains a form or search input that needs immediate keyboard access.

Transformed ancestor anchoring

Scroll a transformed preview shell, then open the popover to verify fixed-position Floating UI anchoring.

04

Props

Props for popover
Name Type Default Required Bindable Description
id text Optional panel id. Defaults to a generated cinder-popover-* id.
open boolean false bind Open state. Bindable. Default false.
placement 'top''bottom''left''right''top-start''top-end''bottom-start''bottom-end' 'bottom-start' Anchor placement. Default 'bottom-start'.
offset number 8 Distance in px between trigger and panel. Default 8.
arrowVisible boolean false Render a directional arrow on the panel. Default false.
label text Accessible name. Sets aria-label when ariaLabelledby is not supplied.
ariaLabelledby text Id of an element labelling the panel. Wins over label.
triggerRef HTMLElement | null null Explicit anchor element. Wins over the snippet-resolved focusable.
trigger snippet Optional trigger snippet rendered inside a wrapper.
children snippet req Panel content. Required.
role 'dialog' | 'group' | 'listbox' 'dialog' ARIA role for the panel. Default 'dialog'.
focusManagement 'panel' | 'preserve' 'panel' Focus behavior for each open session. Default 'panel'.
initialFocus (panel: HTMLElement) => HTMLElementnull Optional callback for choosing the element that receives initial panel focus.
outsideClickIgnoreRefs Array<() => Element | null> [] Additional elements treated as inside for outside dismissal.
wireTriggerAria boolean true Whether Popover owns trigger ARIA wiring. Default true.
closeOnEscape boolean true Whether Escape closes the Popover. Default true. Set false when a parent composite widget (e.g. Combobox) owns Escape for the whole interaction, so the Popover does not shadow the parent's handler while its panel is open.
widthMode 'content' | 'match-anchor' | 'menu' | 'none' 'content' Floating panel width strategy. Default 'content'.