Skip to content

Popover

wu-popover is a small panel of content in a native popover. A button with popovertarget opens and closes it, with no JavaScript. Esc and a click outside close it.

Add the popover attribute to any element and point a button at it with popovertarget. The element stays hidden until the button is pressed, then appears on top of the page, and a click outside or Esc closes it. This is the HTML popover feature built into the browser, so no script is needed. The full demo is under Default.

<button class="wu-btn" type="button" popovertarget="my-note">Details</button>
<div class="wu-popover" id="my-note" popover>
<p>You are billed on the first day of each month.</p>
</div>
Class, attribute or variable Effect
wu-popover Root, on an element with popover. Raised panel with a border and a shadow
wu-popover-title Part. Small semibold heading
wu-popover-actions Part. Row of buttons at the inline end, for an inline confirm
animated Fades and scales in and out, opt-in
--wu-popover--MaxWidth Maximum width, 20rem by default

Billing cycle

You are billed on the first day of each month.

<button class="wu-btn" type="button" popovertarget="popover-default">Details</button>
<div class="wu-popover" id="popover-default" popover>
<h3 class="wu-popover-title">Billing cycle</h3>
<p>You are billed on the first day of each month.</p>
</div>

commandfor with command="toggle-popover" works as the trigger too.

Press Esc to close this panel.

<button class="wu-btn" type="button" commandfor="popover-command" command="toggle-popover">Shortcut</button>
<div class="wu-popover" id="popover-command" popover>
<p>Press Esc to close this panel.</p>
</div>

For a quick confirm next to the control that asked for it, such as deleting one table row, end the popover with wu-popover-actions. The buttons sit at the inline end, so they mirror in right-to-left text. Buttons with popovertargetaction="hide" close the popover after their click handler runs.

Delete this row? You can restore it from the trash for 30 days.

<button class="wu-btn" type="button" popovertarget="popover-confirm">Delete row</button>
<div class="wu-popover" id="popover-confirm" popover>
<p>Delete this row? You can restore it from the trash for 30 days.</p>
<div class="wu-popover-actions">
<button class="wu-btn sm" type="button" popovertarget="popover-confirm" popovertargetaction="hide">Cancel</button>
<button class="wu-btn danger sm" type="button" popovertarget="popover-confirm" popovertargetaction="hide">Delete</button>
</div>
</div>

For an action that cannot be undone, use the confirm modal instead: it takes focus and asks for a deliberate answer.

The panel opens centered under its trigger. When that overflows, it tries above, then edge-aligned placements below and above. The panel has no arrow: after a flip, an arrow could point the wrong way.

The edge-aligned placements follow the popover’s own direction, so a popover inside a dir="rtl" section of a left-to-right page aligns to the right side.

دورة الفوترة

تُفوتر في اليوم الأول من كل شهر.

<button class="wu-btn" type="button" popovertarget="popover-rtl">التفاصيل</button>
<div class="wu-popover" id="popover-rtl" popover>
<h3 class="wu-popover-title">دورة الفوترة</h3>
<p>تُفوتر في اليوم الأول من كل شهر.</p>
</div>

The animated word fades and scales the panel in and out, growing away from its trigger: down when it opens below, up when it opens above. wu-animated on an ancestor turns it on for every popover inside. Motion runs only under prefers-reduced-motion: no-preference.

This panel fades and scales in.

<button class="wu-btn" type="button" popovertarget="popover-animated">Animated</button>
<div class="wu-popover animated" id="popover-animated" popover>
<p>This panel fades and scales in.</p>
</div>
  • Put short, non-essential content in a popover: it closes on Esc and on a click outside.
  • Use a <button> as the trigger, so popovertarget or commandfor links it to the panel.
  • For a hint on a single control, core’s tooltips (data-tooltip) are the lighter choice.
@use "@wovenui/components/popover";

The popover needs no other component. The examples above also use the button.