Popover
Usage
Use a popover for a small amount of related, optional content next to its trigger: a vehicle summary from a table row, quick actions on a work order, a short form like "Snooze reminder". The page stays usable while it's open, and clicking outside or pressing Esc closes it.
- Use a tooltip instead for a single non-interactive line; a menu for a list of commands; a modal when the user must decide before going on.
- Keep it under ~22rem wide and a few lines tall. If it needs scrolling, it should be a drawer or a page.
- Title in sentence case naming the object ("Vehicle KX-24"); actions are verb + object ("Schedule service").
Anatomy
- Trigger — a
<button>withcommandfor+command="toggle-popover"and ananchor-name - Surface —
<div class="popover" popover role="dialog">, overlay surface and shadow - Header (optional) —
.popover__titleand a close button - Body —
.popover__body, may contain links and controls - Footer (optional) —
.popover__footeractions - Arrow (optional) —
.popover__arrow, decorative
Examples
Popover
Closed: the trigger only. Activate it to open the real popover below the button.
Vehicle KX-24
Ford Transit, Northside Depot. 85,200 km — brake inspection is 1,200 km overdue.
Odometer synced 4 min ago from the KX-24 telematics unit.
Placements are logical, so "inline start" is the left in English and the right in Arabic. Near a viewport edge the popover flips with the shared --flip-block / --flip-inline tries.
<button type="button" class="btn btn--secondary" commandfor="pop-kx24" command="toggle-popover"
style="anchor-name: --pop-kx24">KX-24 details</button>
<div id="pop-kx24" class="popover" popover role="dialog" aria-labelledby="kx24-title"
style="position-anchor: --pop-kx24">
<div class="popover__header">
<h4 class="popover__title" id="kx24-title">Vehicle KX-24</h4>
<button type="button" class="btn btn--ghost btn--sm" commandfor="pop-kx24" command="hide-popover" aria-label="Close">…</button>
</div>
<div class="popover__body"><p>…</p></div>
<div class="popover__footer">…</div>
</div>
<!-- Arrow and placements -->
<div class="popover popover--arrow" popover><span class="popover__arrow" aria-hidden="true"></span>…</div>
<div class="popover popover--block-start | popover--inline-start | popover--inline-end" popover>…</div>
API
| Hook | Values | Purpose |
|---|---|---|
.popover[popover] | block | Surface; popover (auto) gives light dismiss and Esc |
commandfor="id" command="toggle-popover | show-popover | hide-popover" | invoker attributes | Open/close without JS; the browser exposes the expanded state on the trigger |
anchor-name / position-anchor | inline style per instance | Ties the surface to its trigger |
.popover--block-start | --inline-start | --inline-end | modifier | Preferred placement (default below, aligned to the inline start) |
.popover--arrow + .popover__arrow | modifier + part | Pointer toward the trigger (block placements) |
.popover__header | __title | __body | __footer | parts | See anatomy |
.is-open | docs-only class | Renders an open popover in page flow (same rule as :popover-open) |
Do and don't
Vehicle summary + "Schedule service" in a popover next to the row.
A 12-field "Edit vehicle" form inside a popover.
Accessibility
| Key | Behavior |
|---|---|
| Enter / Space on trigger | Toggles the popover |
| Tab | From the trigger moves into the popover (it follows the trigger in focus order); can leave it — not a trap |
| Esc | Closes the popover and returns focus to the trigger |
- Role:
role="dialog"(non-modal) witharia-labelledbypointing to the title, or anaria-label. - The trigger's expanded/collapsed state is exposed by the browser for invoker-controlled popovers; add
aria-expandedyourself only when opening from script. - Light dismiss is native for
popover="auto"; focus returns to the invoker when the popover closes with focus inside. - Without anchor positioning the popover opens centered in the viewport — still fully usable.
- The arrow is decorative (
aria-hidden). Forced colors: aCanvasTextborder keeps the surface visible.
Tokens
| Custom property | Purpose |
|---|---|
--color-elevation-surface-overlay | Surface |
--overlay-radius, --overlay-shadow | Shape and elevation |
--color-border-default | Border and arrow edge |
--space-2 | -3 | Gap to the trigger (larger with arrow) |
--motion-duration-base | -fast, --motion-easing-enter | -exit | Fade in and out |