Skip to content
Home Theme Gallery

Popover

The custom element is <hui-popover>.

Overview

The general anchored, non-modal overlay: a trigger slot and a panel that is a native popover in the top layer, so light dismiss and Escape come from the platform. It is the base the dropdown menu, select and combobox are built on.

Example

Popover
Source
<hui-popover>
<hui-button slot="trigger" variant="outline">Details</hui-button>
<div>
<p>Floating content anchored to its trigger.</p>
<a class="hui-link" href="#item">Open item</a>
</div>
</hui-popover>

The Go template that renders it:

<hui-popover>
<hui-button slot="trigger" variant="outline">Details</hui-button>
<div>
<p>{{ .Item.Description }}</p>
<a class="hui-link" href="/items/{{ .Item.ID }}">Open item</a>
</div>
</hui-popover>

API

Attributes2
Attributes
NameTypeDefaultDescription
openbooleanfalseReflected open state. Setting it runs the same side effects as a trigger click, so hui-open is not missed.
placement"top" | "bottom" | "left" | "right""bottom"Which side of the trigger the panel prefers. An unknown value falls back to bottom.
Properties2
Properties
NameTypeDefaultDescription
openbooleanfalseReflects to the open attribute.
placementOverlayPlacement'bottom'Reflects to the placement attribute.
Methods2
Methods
NameTypeDescription
show(from?)-Opens the panel and records from as the element focus returns to. The focused element is the fallback when from is omitted.
hide()-Closes the panel, dispatches hui-close and restores focus.
Events3
Events
NameDescription
hui-openThe panel entered the top layer. It bubbles and is composed, and carries no detail.
hui-closeThe panel left the top layer, whether from hide() or a platform close. It bubbles and is composed, and carries no detail.
click on [slot="trigger"]Opens the panel when closed and closes it when already open. The pointerdown intent is recorded first so the platform's light dismiss does not race the toggle.
Slots2
Slots
NameDescription
triggerThe element the panel is anchored to. It stays in the light DOM so the host owns its markup.
(default)The floating panel content.
CSS custom properties5
CSS custom properties
NameDefaultDescription
--hui-popoveroklch(1 0 0)Panel background.
--hui-popover-foregroundoklch(0.145 0.008 326)Panel text colour.
--hui-borderoklch(0.922 0.005 325.62)Panel border.
--hui-radius-mdcalc(var(--hui-radius, 0.45rem) * 0.8)Panel corner radius.
--hui-shadow-md0 4px 6px -1px oklch(0 0 0 / 0.1), 0 2px 4px -2px oklch(0 0 0 / 0.1)Panel elevation.
::part() hooks2
::part() hooks
NameDescription
anchorThe span carrying the CSS anchor-name the panel points at.
panelThe native popover panel in the top layer.

States

Placement top

placement is the side the panel prefers. It is a preference rather than a promise: the panel flips to the opposite side when there is no room.

Placement top
Source
<hui-popover placement="top">
<hui-button slot="trigger" variant="outline">Above</hui-button>
<div>This panel opens above the trigger.</div>
</hui-popover>

Server-side mechanics

The server owns the trigger markup in slot="trigger", the default-slot panel content, and the open and placement attributes. Render <hui-popover open> to promote the panel to the top layer as the element upgrades, and read open and placement back because both reflect. It is not form-associated and submits nothing, under any name. Because the trigger is light DOM, an hx-swap can replace it while the panel is open; focus restoration then finds the recorded node disconnected and blurs to <body> instead of focusing a detached element. Swapping the popover element itself closes it through disconnectedCallback(), so nothing is left floating over the page.

Accessibility

  • Non-modal: the page behind it stays interactive and focus is not trapped.
  • The panel is a real popover="auto", so it is promoted to the top layer and is never clipped by an ancestor's overflow, transform or stacking context.
  • The base sets no role on the panel; the host's content supplies its semantics.
  • Focus returns to the element passed to show() on close, or is blurred when that element has been swapped away.
  • Escape and a click outside both dismiss through the platform, and both dispatch hui-close.

Keyboard

Keyboard
KeysAction
EscapeCloses the panel through the platform's popover handling and returns focus to the trigger.
Enter, SpaceActivate the slotted trigger through its own control, which opens or closes the panel.
Tab, Shift+TabMove through the page normally; the panel is non-modal and traps nothing. Leaving the panel with Tab closes it.

Gotchas

None recorded.