Popover

A surface-tier panel anchored to a trigger, holding rich content.

Basic

A plain popover is a .popover__title over a .popover__body. Adding a .popover__header turns it into a panel: the root padding drops so header and footer dividers run edge to edge, and each part owns its padding. Give the .popover an id + data-stisla-popover, point a data-stisla-popover-trigger="id" button at it, and the @stisla/vanilla layer positions it with Floating UI, traps focus, and closes on outside click or ESC. The arrow is injected automatically, pointing back at the trigger. The demos below are live.

Keyboard

Hover-trigger popovers open on focus too, so keyboard users get the same affordance as hover users. Focus is not trapped, so Tab can leave the panel naturally. Pointer down outside the popover also dismisses.

  • Enter / Space: open the popover when the trigger is focused (click-trigger mode)
  • Escape: close the popover and return focus to the trigger
  • Tab: move focus through the panel and out the other side

With a close chip

Drop in .popover__close for a corner dismiss affordance; the title clears it automatically.

Placements

data-stisla-popover-placement picks the resting side. Floating UI flips automatically when the chosen side would overflow the viewport.

Hover trigger

Add data-stisla-popover-trigger-mode="hover focus" to open on hover and keyboard focus. The 100ms close delay bridges the cursor from the trigger into the popover so it stays open while you read it.

Rich content

Author the body with whatever markup the popover needs. Paragraphs, links, buttons, and form bits all work. There's no string-content opt-in.

Panel

A .popover__header holds the title with a trailing .popover__action, a list sits in the body, and a .popover__footer closes it out. Add .popover--menu when the body is a list of rows so each .media row carries its own hover and the panel reads like a menu. Each row's leading slot takes an icon box or an avatar.

Imperative

Reach a marked popover via Stisla.get(document.getElementById('id')) and call Stisla.Popover.getOrCreate(el).open() when you need to drive it from script without a click trigger.

Events

Four events fire on the .popover root. The opening and closing events are cancelable.

stisla:popover:opening fires before the panel mounts. Call preventDefault() to abort.

stisla:popover:opened fires once the panel is positioned and visible.

stisla:popover:closing fires before the panel dismisses. Call preventDefault() to keep it open.

stisla:popover:closed fires once the panel is fully hidden and focus has returned to the trigger.

Customization

These variables retune the panel. Override on the root or any wrapper.

VariableUse
--popover-z-indexOverlay stacking order
--popover-min-width / -max-widthPanel width bounds
--popover-padding-block / -padding-inlineRoot padding (plain popover only; a panel drops it)
--popover-color / -bg / -border-colorPanel text, fill, and rim
--popover-radius / -shadowPanel corner radius and elevation
--popover-title-color / -font-size / -font-weightTitle type
--popover-body-color / -font-size / -line-heightBody type (muted by default)
--popover-header-gap / -header-padding-block / -header-padding-inlineHeader row layout
--popover-footer-padding-block / -footer-padding-inlineFooter padding
--popover-close-size / -close-color / -close-bg-hoverClose chip size and paint
--popover-arrow-sizeCaret square size
--popover-transition-durationFade and slide timing; zeroed under reduced-motion