usePopover @astryx-svelte/core v0.3.0 · Popover
Usage
Headless hook for click-triggered popovers with focus trapping. Combines useLayer with useFocusTrap, auto-focus, light dismiss, Escape handling, and an optional hidden close button for accessible dialog-like popover behavior. Use for custom interactive floating content that needs keyboard navigation.tsimport { Popover } from '@astryx-svelte/core';
Best practices
| Guidance | Practices |
|---|---|
| Do | Use for interactive content such as menus, pickers, forms, and command panels that need focus management. |
| Do | Prefer the Popover component for standard trigger-content pairs; use the hook for custom trigger patterns. |
| Don't | Use for non-interactive hover previews: use useHoverCard or useTooltip instead. |
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
onShow | () => void | — | Callback fired when the popover becomes visible. |
onHide | () => void | — | Callback fired when the popover is hidden. Use this to return focus to the trigger when needed. |
xstyle | StyleArg | — | StyleX styles applied to the popover content wrapper, after the default surface styles. |
hasLightDismiss | boolean | true | Whether clicking outside dismisses the popover. |
hasEscapeDismiss | boolean | true | Whether pressing Escape dismisses the popover. Only takes full effect together with hasLightDismiss: false, since native light dismiss also closes on Escape. |
hasAutoFocus | boolean | true | Whether to automatically focus the first focusable element when opened. |
hasCloseButton | boolean | true | Whether to include a hidden close button that appears for keyboard users. |
closeButtonLabel | string | 'Close popover' | Accessible label for the hidden close button. |
dialogLabel | string | — | Accessible label for the popover dialog (only applies when role is "dialog"). Provide one when there is no visible title. |
role | 'none' | 'dialog' | 'dialog' | ARIA role on the content wrapper. Use "dialog" for genuine dialog content; use "none" for listbox/menu popups whose own content role should be exposed and whose trigger keeps DOM focus. |
isModal | boolean | true | Whether a dialog-role popover is modal (aria-modal). Only applies when role is "dialog". |
hasSurface | boolean | true | Whether to apply the default popover surface background, radius, and shadow. |
Returns
| Field | Type | Default | Description |
|---|---|---|---|
triggerRef | (el: HTMLElement | null) => void | — | Ref callback to attach to the trigger element for CSS anchor positioning. Element references are attachments here. The port returns an |
contentRef | HTMLDivElement | null | — | Ref for the popover content container used by focus trapping. Element references are attachments here. The port returns an |
anchorId | string | — | CSS anchor name for advanced positioning cases. |
show | (options?: { skipAutoFocus?: boolean; }) => void | — | Imperatively show the popover. skipAutoFocus preserves current focus for input-triggered popovers. |
hide | () => void | — | Imperatively hide the popover. |
toggle | () => void | — | Toggle the popover open or closed. |
isOpen | boolean | — | Whether the popover is currently open. |
id | string | — | Unique ID for aria-describedby or aria-controls. |
render | (children: string | Snippet, props?: ContextRenderProps) => string | Snippet | — | Render function for anchor-positioned popover content. Pass placement and alignment here. Logical: start/end resolve against the popover's own inherited direction (RTL mirrors in pure CSS). A Svelte hook cannot return markup. This hook returns state only; render its companion component and pass the hook’s value to it.Upstream declares |
triggerProps | { 'aria-haspopup': 'dialog' | 'true'; 'aria-expanded': boolean; 'aria-controls': string; } | — | ARIA attributes to spread onto the trigger element. aria-haspopup reflects the popover role. |
Examples
Common configurations, variations, and states.usePopover — Quick Actions
Custom quick-actions popover using usePopover for trigger refs, ARIA attributes, and focus trapping.