Popover
A trigger button and native popover panel for menu-like floating content.
Usage
Use standalone; the panel usually wraps MenuList.
<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.
<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
| Name | Type | Default | Description |
|---|---|---|---|
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 |
open | boolean | false | Bindable open state; can be observed and controlled |
hover | boolean | false | Opens on pointer enter and focus for hover-capable primary pointers |
position | Position | "bottom" | Native anchor placement position |
align | Align | "start" | Native anchor placement alignment |
offset | number | 0 | Gap from the anchor edge in px |
autoFlip | boolean | true | Enables native fallback placement |
matchWidth | boolean | false | Sets panel min-width to the anchor width |
ariaRole | PopoverRole | - | Sets the panel role, such as menu, listbox, or dialog |
manual | boolean | false | Uses popover="manual" and disables native light-dismiss behavior |
arrow | boolean | false | Renders the resolved placement caret part and sets data-svs-placement; also auto-applies overflow: visible to the panel so the caret can render outside |
attach | Attachment | - | Svelte attachment on the trigger |
element | HTMLButtonElement | - | Bindable trigger element |
styling | SVSClass | - | Styling override |
variant | SVSVariant | NEUTRAL | Popover 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-haspopupfromariaRoleor"true"when unset,aria-expandedfrom the open state, andaria-controlspointing to the panel. - Panel (
whole<div>):rolefrom theariaRoleprop 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
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.