Composite
Popover Requires JS
A floating panel anchored to a trigger. Holds richer content than a Tooltip — small forms, action menus, settings panels — with full keyboard navigation. Built on the native Popover API where supported.
About
Overview
Popovers open on click (not hover) and stay open until the user dismisses them. Use them for short forms, mini settings panels, or contextual choices that don't warrant a full Dialog. The trigger is always a button; the content can be anything keyboard-friendly.
Popover vs Dialog vs Tooltip. Tooltip = passive hint on hover. Popover = small interactive panel anchored to a trigger. Dialog = modal that blocks the rest of the page.
Live
Demo
Two popovers share this page on purpose: each panel must open against its own trigger, never against the last trigger in the document. Filters dismisses with Esc or a click outside; Sort adds an explicit .ren-popover-footer.
<button type="button" id="filters-trigger">Filters</button>
<ren-popover trigger-id="filters-trigger" placement="bottom" aria-label="Filters">
<div class="ren-popover-header">Filter posts</div>
<div class="ren-popover-body"><!-- checkboxes, radios, etc. --></div>
<div class="ren-popover-footer">…</div>
</ren-popover>
Reference
API
| Class | Effect |
|---|---|
.ren-popover | The floating panel. Added to <ren-popover> by the component — you don't write it by hand. |
.ren-popover-header / -body / -footer | The three content slots inside the panel. |
.ren-popover-arrow | Arrow pointing at the trigger. Injected automatically when missing. |
Web Component attributes
| Attribute | Type | Default | Notes |
|---|---|---|---|
placement | "top" | "right" | "bottom" | "left" | "bottom" | Side relative to the trigger; auto-flips when there isn't room. |
trigger-id | string | — | id of the trigger. Without it the component looks for a child [data-popover-trigger], then the previous sibling. Give every popover on a page its own trigger id. |
offset | number (px) | 8 | Gap between trigger and panel in the JS positioning fallback. |
Open state is driven by the methods open(), close() and toggle(); the component fires ren-open and ren-close.
Inclusive by default
Accessibility
- Trigger has
aria-haspopup="dialog"andaria-expandedkept in sync. - Open: focus moves to the first focusable element inside the popover.
- Close: focus returns to the trigger.
- Esc closes the popover. Click outside also closes.
Patterns
Examples
Quick filters panel
<button type="button" id="filters-trigger" class="ren-btn ren-btn-secondary">Filters</button>
<ren-popover trigger-id="filters-trigger" aria-label="Filters">
<div class="ren-popover-body"><form>…</form></div>
</ren-popover>