Popover
hc-popover styles the native popover attribute. The browser handles
open/close, top-layer rendering, light-dismiss, and Escape-to-close —
no JavaScript required.
Basic HTML
Section titled “Basic HTML”A short, focused message. The browser closes me on Escape or by clicking outside.
<button class="hc-button" type="button" popovertarget="filter-popover"> Filter</button>
<div id="filter-popover" class="hc-popover" popover> <p>Choose filters here.</p></div>The popover attribute defaults to popover="auto", which means:
- Light-dismiss on outside click.
- Escape-to-close.
- Only one
autopopover is open at a time.
For a popover that ignores light-dismiss, use popover="manual" and
close it yourself with element.hidePopover().
JavaScript
Section titled “JavaScript”The basic light-dismiss popover above works from the native Popover API alone. The directional placement and htmx auto-close features below need behaviors — install the ones you use once at startup:
import { installPopover, installClosePopover } from '@hypermedia-components/core';installPopover(); // data-side / data-align anchoring + aria syncinstallClosePopover(); // close on a successful htmx request (optional)The zero-config @hypermedia-components/core/behaviors entry installs both
automatically.
Directional placement
Section titled “Directional placement”A bare popover is positioned by the browser (centred in the top layer). To
anchor it to its trigger with a side and alignment, add data-side
(top / right / bottom / left) and optionally data-align (start /
center / end, default center). installPopover() wires the anchoring
and keeps aria-expanded / aria-controls on the trigger in sync. Add
data-arrow for a small pointer.
Opens to the inline-end, top-aligned.
<button class="hc-button" type="button" popovertarget="filters">Filter</button>
<div id="filters" class="hc-popover" popover data-side="right" data-align="start" data-arrow> <p style="margin:0;">Opens to the inline-end, top-aligned.</p></div>Placement uses CSS Anchor Positioning (position-area) where supported
and position-try-fallbacks to flip at the viewport edge. The same
attributes drive a JS fallback (getBoundingClientRect) for engines without
it, so both paths place the popover identically. The shared mechanics —
both paths, the arrow, and the --hc-anchored-* knobs — are documented in
Fundamentals → Anchored positioning.
htmx usage
Section titled “htmx usage”A popover can host an htmx-driven form. To close the popover after a
successful request, add the data-hc-close-popover-on-success attribute
and install the installClosePopover() behavior (bundled in
@hypermedia-components/core/behaviors).
<form class="hc-form" data-hx-get="/items" data-hx-target="#results" data-hc-close-popover-on-success> …</form>The behavior listens for htmx:afterRequest, checks for success, and
calls closest('[popover]').hidePopover().
Accessibility
Section titled “Accessibility”- A popover is not automatically a menu. Setting
role="menu"and providing arrow-key navigation are separate concerns documented elsewhere. - The trigger (the element with
popovertarget) gets focus back when the popover closes — this is browser behavior. - For tooltip-like popovers triggered by hover or focus, use the
[popovertargetaction="show"]attribute family or a custom hover handler. Hover-only tooltips are not accessible to keyboard users by themselves. - The popover’s accessible name comes from its content; if the popover
has no visible title, add
aria-label.
Theming tokens
Section titled “Theming tokens”| Token path | Purpose |
|---|---|
popover.bg / -fg / -border | Surface colors. |
popover.radius | Border radius. |
popover.padding | Inner padding. |
popover.min-width / -max-width | Size bounds. |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-popover-bg | -fg | -border--hc-popover-radius | -padding--hc-popover-min-width | -max-widthRelated
Section titled “Related”- Dialog — modal variant for confirmation flows.
filter-popoverrecipe — popover + form + htmx.