Popovers
tier 2 — classesA small amount of content anchored to the control that opened it — why a row is pending, what a number means, the detail behind a figure. A list of actions is a menu; one line with no markup in it is a hover hint.
Popover
Live — open it. The popover attribute is
required, and so is opening it from a popovertarget control, which
also makes that button the popover's implicit anchor, so nothing here declares an
anchor-name. The platform then supplies the top layer, light dismiss,
Escape and focus handling, so unlike .menu this needs no scrim and
no key handler. It closes on a scroll that moves its trigger, because an anchored panel's
position is fixed at the moment it opens.
Priority 2 carries a four-hour response target measured from the first warehouse update, not from when the order reached this queue.
Reassigning does not restart the clock. Only a priority change does.
Below 0.60 the reservation is never auto-applied. Between 0.60 and 0.90 it waits for a human. Above 0.90 it applies if the action type is on the automation list.
<div class="sedna-row-wrap">
<button class="btn" type="button" popovertarget="sla-detail">Why is this overdue?</button>
<div class="popover" id="sla-detail" popover>
<strong class="popover-title">Response target breached 2h ago</strong>
<p>
Priority 2 carries a four-hour response target measured from the first warehouse
update, not from when the order reached this queue.
</p>
<p>Reassigning does not restart the clock. Only a priority change does.</p>
</div>
<button class="btn" type="button" popovertarget="confidence-detail">
Confidence 0.87
</button>
<div class="popover" id="confidence-detail" popover>
<strong class="popover-title">How the score is read</strong>
<p>
Below 0.60 the reservation is never auto-applied. Between 0.60 and 0.90 it waits for a
human. Above 0.90 it applies if the action type is on the automation list.
</p>
</div>
</div>
Opened from something that is not a button
A count inside a link, an avatar or a table cell cannot be a popovertarget
button. data-popover="<id>" on any element opens that popover by click,
Enter or Space and anchors it there, placed exactly as a button's
would be; the click is taken, so the link around it does not follow. Give the trigger a
role and a tabindex when it is not focusable already.
sednaUi.popover.show(panel, trigger) does the same from your own script.
3 invoices and 2 delivery notes. They go out with the next run at 14:00.
<nav class="nav" style="max-width:240px">
<a class="nav-link" href="#">
<i class="ri-send-plane-line"></i><span>Outbox</span>
<span class="nav-count" data-popover="outbox-detail" role="button" tabindex="0" aria-label="5 waiting — show which">5</span>
</a>
</nav>
<div class="popover" id="outbox-detail" popover>
<strong class="popover-title">5 waiting to send</strong>
<p>3 invoices and 2 delivery notes. They go out with the next run at 14:00.</p>
</div>
A hover card
data-popover-hover beside data-popover opens the panel when the
pointer rests on the trigger or the focus reaches it, after --hover-delay
(400ms), and closes it once the pointer has left both — so the reader can move onto the card.
A click pins it until it is dismissed or the trigger is clicked again. Use it for a detail
worth a glance; a word of help is a hover hint.
Delivery on 14 Nov, 09:00–11:00, confirmed by the carrier.
<p>
Delivery on
<span class="text-mono" data-popover="slot-card" data-popover-hover tabindex="0" role="button">14 Nov, 09:00–11:00</span>,
confirmed by the carrier.
</p>
<div class="popover" id="slot-card" popover>
<strong class="popover-title">Delivery window</strong>
<div class="kv"><span class="k">Carrier</span><span class="v">Northwind Retail</span></div>
<div class="kv"><span class="k">Driver contact</span><span class="v">alex.fischer@example.com</span></div>
</div>
A hover card beside a click of its own
Live — rest on the button, then click it.
data-popover-hover="only" is for a trigger whose click does something else —
here it opens a dialog, and the card is a glance at what the dialog holds. Hover and focus open
the card; a click neither opens nor pins it, runs the trigger's own action and closes the card,
so it never sits above the dialog the click opened.
<button class="btn" type="button" data-popover="hosting-summary" data-popover-hover="only"
onclick="document.getElementById('hosting-costs').showModal()">
<i class="ri-server-line"></i> <span>Hosting costs</span>
</button>
<div class="popover" id="hosting-summary" popover>
<strong class="popover-title">This month so far</strong>
<div class="kv"><span class="k">Spent</span><span class="v">41.20 EUR</span></div>
<div class="kv"><span class="k">Forecast</span><span class="v">63.00 EUR</span></div>
</div>
<dialog class="modal" id="hosting-costs" aria-labelledby="hosting-costs-title">
<form method="dialog">
<div class="modal-header">
<h3 id="hosting-costs-title">Hosting costs</h3>
<button class="modal-close" value="close" aria-label="Close"><i class="ri-close-line"></i></button>
</div>
<div class="modal-body">
<p>orders-console-01 and build-runner-04, billed daily. The full breakdown by service is in the invoice.</p>
</div>
<div class="modal-footer">
<button class="btn" value="close">Close</button>
</div>
</form>
</dialog>
Four shapes
A definition, a key/value detail block, a small table, and one with an action in it. One
trailing action that acts on what the panel is explaining is fine; a list of actions is a
.menu. popovertargetaction="hide" closes it from inside with no
script at all.
The panel is width: max-content, so each of these is as wide as what is in it
and no wider. That is what makes .kv's gap load-bearing here and nowhere else:
space-between has no free space to distribute in a shrink-to-fit box, so
without the gap the key would run straight into the value. The table takes
.popover--flush, which drops the panel's padding so the table reaches the
rounded corners instead of sitting in a frame inside a frame — the title keeps its own
inset, and the last row gives up its rule to the panel's border.
Stock reserved for an order but not yet picked. A hold expires after 48 hours and the stock returns to the pool.
| Warehouse | Free | Held |
|---|---|---|
| Rotterdam | 128 | 12 |
| Hamburg | 0 | 4 |
| Lyon | 46 | 0 |
Lines 3 and 5 have no free stock in any warehouse. The order ships when either arrives.
<div class="sedna-row-wrap sedna-gap-2">
<button class="btn" type="button" popovertarget="pop-define">What is a hold?</button>
<div class="popover" id="pop-define" popover>
<strong class="popover-title">Hold</strong>
<p>Stock reserved for an order but not yet picked. A hold expires after 48 hours and the
stock returns to the pool.</p>
</div>
<button class="btn" type="button" popovertarget="pop-kv">ORD-4182 detail</button>
<div class="popover" id="pop-kv" popover>
<strong class="popover-title">ORD-4182</strong>
<div class="kv"><span class="k">Placed</span><span class="v">3 Aug, 09:14</span></div>
<div class="kv"><span class="k">Customer</span><span class="v">Priya Nair</span></div>
<div class="kv"><span class="k">Region</span><span class="v">EU-West</span></div>
<div class="kv"><span class="k">Lines</span><span class="v">5, two on hold</span></div>
</div>
<button class="btn" type="button" popovertarget="pop-table">Stock by warehouse</button>
<div class="popover popover--flush" id="pop-table" popover>
<strong class="popover-title">On hand</strong>
<table class="table">
<thead><tr><th>Warehouse</th><th class="col-num">Free</th><th class="col-num">Held</th></tr></thead>
<tbody>
<tr><td>Rotterdam</td><td class="col-num">128</td><td class="col-num">12</td></tr>
<tr><td>Hamburg</td><td class="col-num">0</td><td class="col-num">4</td></tr>
<tr><td>Lyon</td><td class="col-num">46</td><td class="col-num">0</td></tr>
</tbody>
</table>
</div>
<button class="btn" type="button" popovertarget="pop-action">Two lines on hold</button>
<div class="popover" id="pop-action" popover>
<strong class="popover-title">Awaiting stock</strong>
<p>Lines 3 and 5 have no free stock in any warehouse. The order ships when either arrives.</p>
<div class="sedna-row sedna-end sedna-gap-1" style="margin-top:10px">
<button class="btn btn--sm" type="button" popovertarget="pop-action" popovertargetaction="hide">Close</button>
<button class="btn btn--sm btn--brand btn--solid" type="button">Split the order</button>
</div>
</div>
</div>
.popover is in the top layer, which no z-index reaches, and is ordered
by when it was promoted — so one opened from inside a modal dialog sits over the
dialog. Its rung on the z-order scale, 550, is the fallback
for a panel that carries the class without the attribute.