Markdown:
Components

Popover

A trigger button and native popover panel for menu-like floating content.

Usage

Use standalone; the panel usually wraps MenuList.

Svelte
<Popover label="Menu" {...props}>
  <MenuList {...props} />
</Popover>

Anatomy

The class attribute values represent part names. Other attributes represent their corresponding props. The panel usually wraps MenuList.

Svelte
<button class="label" popovertarget aria-haspopup aria-expanded aria-controls>
  {label}
</button>
<div class="whole" popover role style data-svs-placement>
  <div class="top" aria-hidden conditional: arrow, placement=bottom></div>
  <div class="left" aria-hidden conditional: arrow, placement=right></div>
  <div class="main">{children}</div>
  <div class="bottom" aria-hidden conditional: arrow, placement=top></div>
  <div class="right" aria-hidden conditional: arrow, placement=left></div>
</div>

Button trigger plus a [popover] panel, using the native Popover API and CSS Anchor Positioning only, with no JavaScript positioning fallback. open syncs both ways between programmatic state and native toggle events. position, align, offset, matchWidth, and autoFlip derive the native placement style; when arrow is enabled, a measurement effect reads the resolved trigger/panel rects on open, scroll, and resize so the rendered caret follows native flips and data-svs-placement exposes the resolved side, and overflow: visible is applied to the panel so the caret renders outside its box. hover adds pointer/focus opening only where the primary pointer can hover, otherwise it behaves like native click/focus opening. The component always provides MenuContainerContext so a nested MenuList can focus its first enabled item and close through the container. manual switches the panel to popover="manual" and disables native light-dismiss behavior.

Props

NameTypeDefaultDescription
label*Snippet-Trigger label; receives open state and variant as arguments
children*Snippet-Panel content; receives the variant as its argument and usually renders a MenuList
openbooleanfalseBindable open state; can be observed and controlled
hoverbooleanfalseOpens on pointer enter and focus for hover-capable primary pointers
positionPosition"bottom"Native anchor placement position
alignAlign"start"Native anchor placement alignment
offsetnumber0Gap from the anchor edge in px
autoFlipbooleantrueEnables native fallback placement
matchWidthbooleanfalseSets panel min-width to the anchor width
ariaRolePopoverRole-Sets the panel role, such as menu, listbox, or dialog
manualbooleanfalseUses popover="manual" and disables native light-dismiss behavior
arrowbooleanfalseRenders the resolved placement caret part and sets data-svs-placement; also auto-applies overflow: visible to the panel so the caret can render outside
attachAttachment-Svelte attachment on the trigger
elementHTMLButtonElement-Bindable trigger element
stylingSVSClass-Styling override
variantSVSVariantNEUTRALPopover variant

* required. Other HTMLButtonAttributes are passed to the trigger <button> via rest props; class is merged onto the trigger.

Styling

To learn more, see Styling.

Variant Management

No automatic switching.

Default Class Name

svs-popover

Behavior

Button trigger plus a [popover] panel, using the native Popover API and CSS Anchor Positioning only, with no JavaScript positioning fallback. open syncs both ways between programmatic state and native toggle events. position, align, offset, matchWidth, and autoFlip derive the native placement style. When arrow is enabled, a measurement effect reads the resolved trigger/panel rects on open, scroll, and resize so the rendered caret follows native flips and data-svs-placement exposes the resolved side, and overflow: visible is applied to the panel so the caret renders outside its box. hover adds pointer/focus opening only where the primary pointer can hover, otherwise it behaves like native click/focus opening. The component always provides MenuContainerContext so a nested MenuList can focus its first enabled item and close through the container. manual switches the panel to popover="manual" and disables native light-dismiss behavior.

Accessibility

ARIA Roles and Attributes

The component applies these automatically:

  • Trigger (label <button>): aria-haspopup from ariaRole or "true" when unset, aria-expanded from the open state, and aria-controls pointing to the panel.
  • Panel (whole <div>): role from the ariaRole prop when supplied.
  • Arrow caret (top / bottom / left / right <div>, when rendered): aria-hidden="true".

Set ariaRole to match the panel content, such as "menu" when the panel hosts a MenuList. See MenuList for the common menu panel case.

Standards Basis

Popover is built on a native <button> trigger and the native Popover API, so keyboard and assistive-technology support follows the browser standard for button controls and popover dismissal. See the Concepts standards-first guidance for the library's approach.

Exports

Types

TypeScript
interface PopoverProps extends Omit<HTMLButtonAttributes, "children" | "style" | "popovertarget" | "popovertargetaction"> {
  label: string | Snippet<[boolean, string]>; // trigger; Snippet<[open, variant]>
  children: Snippet<[string]>; // panel content; Snippet<[variant]>; usually renders a MenuList
  open?: boolean; // bindable (false); observe + control
  hover?: boolean; // (false); open on pointerenter / focusin where the primary pointer can hover
  position?: Position; // ("bottom")
  align?: Align; // ("start")
  offset?: number; // (0); gap from the anchor edge, px
  autoFlip?: boolean; // (true); native fallback placement
  matchWidth?: boolean; // (false); panel min-width = anchor width
  ariaRole?: PopoverRole; // panel role
  manual?: boolean; // (false); popover="manual" disables light-dismiss
  arrow?: boolean; // (false); render the resolved placement caret part (`top`/`bottom`/`left`/`right`) and `data-svs-placement`
  attach?: Attachment<HTMLButtonElement>;
  element?: HTMLButtonElement; // bindable
  styling?: SVSClass;
  variant?: SVSVariant; // (VARIANT.NEUTRAL)
  // other HTMLButtonAttributes are passed to the trigger via ...rest; `class` is merged onto the trigger
  // style, popovertarget, and popovertargetaction are component-owned
}
type PopoverReqdProps = "label" | "children";
type PopoverBindProps = "open" | "element";
type Position = "top" | "right" | "bottom" | "left";
type Align = "start" | "center" | "end";
type PopoverRole = "menu" | "listbox" | "dialog";

Others

No additional exports are available.

Examples

The example code uses Tailwind CSS along with SVSClass.

Basic

With Interactive Variant

Preset for Demo
Enter variant as you like