Popover

Floating content anchored to a trigger element. It supports modal and non-modal interaction patterns, outside interaction handling, and configurable positioning.

Anatomy

Popover.Root shares open state and the trigger reference between Popover.Trigger and Popover.Content. The content renders in a portal and positions itself against the trigger.

<script>
	import { Popover } from '@human-kit/ui';
</script>

<Popover.Root>
	<Popover.Trigger>Open</Popover.Trigger>
	<Popover.Content>
		<div>Content</div>
	</Popover.Content>
</Popover.Root>

Placement

Use placement on Popover.Content to pick the preferred side and alignment (12 options, e.g. top, bottom-start, right-end; default bottom), and offset to control the gap from the trigger. With shouldFlip (default true), the panel falls back to the opposite side when space runs out; the resolved side is exposed as data-placement.

By default the popover is modal: focus is trapped, scroll is locked, and outside content is aria-hidden. Set nonModal to allow interaction with the rest of the page — non-modal popovers close when focus leaves them (shouldCloseOnBlur defaults to true in that mode).

Usage guidelines

  • Use Popover.Root to share open state and trigger reference.
  • Use Popover.Trigger as the opener button.
  • Use Popover.Content inside Popover.Root, or in standalone mode with open, triggerRef, and onOpenChange.
  • Configure nonModal, shouldCloseOnInteractOutside, and shouldCloseOnBlur to match your interaction model.
  • onOpenChange(open, details) reports why the state changed (details.reason) and supports details.cancel() to prevent the transition.
  • Style enter/exit motion via the data-state / data-entering / data-exiting attributes; exit animations keep the panel mounted until its CSS transition or animation finishes.

Accessibility

  • Popover.Content renders role="dialog"; Popover.Trigger renders a button with aria-haspopup="dialog" and aria-expanded.
  • Modal popovers trap focus, lock body scroll, and hide outside content from assistive technology; use initialFocus to pick the first focused element.
  • Escape closes the popover and returns focus to the trigger; outside interaction closes it unless shouldCloseOnInteractOutside={false}.
  • Non-modal popovers keep the page interactive and close when focus moves outside the trigger and panel.

API reference

Root

State container for the popover. Shares open state, the trigger reference, and open/close/toggle actions with the trigger and content parts.

Prop Type Default

* required. Native HTML attributes of the underlying element are also accepted.

Content

The floating role="dialog" panel, rendered in a portal and positioned against the trigger. Works inside Popover.Root or in standalone controlled mode via `open`, `triggerRef`, and `onOpenChange`.

Prop Type Default

* required. Native HTML attributes of the underlying element are also accepted.

Data attribute Description
data-entering Present while the enter animation is running.
data-exiting Present while the exit animation is running.
data-placement The resolved side of the trigger the panel is on ("top" | "right" | "bottom" | "left").
data-state "open" while the popover is open, "closed" during exit.

Trigger

Button that registers itself as the popover trigger and toggles the popover on click (aria-haspopup="dialog", aria-expanded).

Prop Type Default

* required. Native HTML attributes of the underlying element are also accepted.

Data attribute Description
data-popover-trigger Identifies the trigger button.

Overlay

Optional backdrop rendered behind the popover. Place it as a sibling of Popover.Content inside Popover.Root; it runs its own enter/exit presence so it fades in step with the panel.

Prop Type Default

* required. Native HTML attributes of the underlying element are also accepted.

Data attribute Description
data-entering Present while the enter animation is running.
data-exiting Present while the exit animation is running.
data-popover-overlay Identifies the overlay element.
data-state "open" while the popover is open, "closed" during exit.