How a popover works
A popover is content that floats above the page, anchored to the thing that opened it: a menu, a hint, a small panel. Two separate problems have to be solved, and the browser only solves the first.
What the browser gives you: the popover attribute
Put popover on an element and popovertarget on a button, and you have a working popover with no script at all:
<button type="button" class="i80-button i80-button--color-secondary i80-button--size-medium" popovertarget="quota-note">
<span class="i80-button__text">What counts towards the quota?</span>
</button>
<div id="quota-note" popover class="i80-typography-body-200 i80-foreground-primary"
style="max-width: 20rem; padding: 16px; background: var(--i80-color-surface-primary); border: 1px solid var(--i80-color-border-primary); border-radius: 6px; box-shadow: var(--i80-elevation-high-box-shadow)">
Every running service counts once, whichever region it is in. Stopped services do not count.
</div>
What you get for free:
- The popover is promoted to the top layer, so it is never clipped by an
overflow: hiddenancestor and never lands behind something with a higherz-index. Stacking contexts stop being your problem. - "Light dismiss": a click outside it or
Esccloses it. - Opening one
popover="auto"closes any other, so two menus cannot be open at once. showPopover(),hidePopover()andtogglePopover()from script, and:popover-openin CSS.
popover="manual" opts out of light dismiss and out of closing its siblings — that is what a tooltip wants, because a tooltip is not something you dismiss.
What the browser does not give you: position
The popover attribute says nothing about where the content appears. Placing it against its anchor, flipping it when there is no room below, and nudging it sideways at the edge of the window is the second problem, and we use Floating UI for it — the same library behind Dropdown and Tooltip.
So before you build anything: the two elements that already combine both are almost certainly what you want.
A menu, on click
Dropdown is a button and a list in a native popover. Esc, a click outside and the arrow keys all work, and the list flips and shifts to stay on screen:
<i80-dropdown text="Actions" color="secondary">
<i80-dropdown-title>Plan</i80-dropdown-title>
<i80-dropdown-item href="#edit" icon="edit">Edit</i80-dropdown-item>
<i80-dropdown-item icon="duplicate">Duplicate</i80-dropdown-item>
<i80-dropdown-separator></i80-dropdown-separator>
<i80-dropdown-item color="critical" icon="trash">Delete</i80-dropdown-item>
</i80-dropdown>
A hint, on hover and focus
Tooltip opens when the pointer enters the trigger and when the trigger takes focus, and closes when the pointer leaves, when focus leaves, and on Esc. Hover alone is not enough — a hint that only appears on hover is unreachable from the keyboard — so both are wired together:
<i80-tooltip text="Copies the plan with all its tasks">
<i80-button icon="duplicate" icon-only color="secondary">Duplicate</i80-button>
</i80-tooltip>
<i80-tooltip text="Only people on the team can see it">Visibility</i80-tooltip>
Where it opens
Both elements take the preferred side, and both give it up when there is no room: the content flips to the opposite side, then shifts along the edge, rather than disappearing off the window.
<i80-tooltip text="Above, the default" placement="top">Top</i80-tooltip>
<i80-tooltip text="Below the trigger" placement="bottom">Bottom</i80-tooltip>
<i80-tooltip text="To the left" placement="left">Left</i80-tooltip>
<i80-tooltip text="Lined up with the start edge" placement="bottom-start">Bottom start</i80-tooltip>
<i80-dropdown text="Opens down and right" color="secondary" size="small" position="bottom-right">
<i80-dropdown-item>Newest first</i80-dropdown-item>
<i80-dropdown-item>Oldest first</i80-dropdown-item>
</i80-dropdown>
<i80-dropdown text="Opens up and left" color="secondary" size="small" position="top-left">
<i80-dropdown-item>Newest first</i80-dropdown-item>
<i80-dropdown-item>Oldest first</i80-dropdown-item>
</i80-dropdown>
<i80-tooltip> uses placement, with the twelve Floating UI values (top, top-start, top-end, and the same for bottom, left and right). <i80-dropdown> uses position, with the four corners. Both are a preference, not a promise — at the edge of the window, staying visible wins.
Building your own
If you need an anchored overlay that is neither a menu nor a hint:
- Put
popoveron the panel andpopovertargeton the button, so the browser handles the layer,Escand the click outside. - Position it with Floating UI —
flipto swap sides,shiftto slide along the edge,offsetfor the gap,arrowfor an arrow — or with CSS anchor positioning where the browsers you support have it. - If the toggle shows and hides a panel rather than floating one, you want
aria-expandedinstead — see Show and hide.
Attributes
The two elements that give you a positioned popover:
| Element | Attributes |
|---|---|
<i80-dropdown> |
text, color, size, icon, position (bottom-right · bottom-left · top-right · top-left), width, height, match-toggle-width, inline, open. Methods show(), hide(). Events i80-open, i80-close. |
<i80-tooltip> |
text, placement (top · bottom · left · right, each also -start and -end). |
The popover attribute
This is the browser's own API, not ours — see MDN.
| Member | Notes |
|---|---|
popover |
On the panel. auto (the default) closes on Esc and on a click outside, and closes other auto popovers when it opens. manual does neither. |
popovertarget |
On a <button>: the id of the popover it toggles. Nothing else works here. |
popovertargetaction |
toggle (the default), show or hide. |
showPopover() / hidePopover() / togglePopover() |
From script. |
:popover-open |
The CSS selector for an open popover. |
toggle event |
Fired on the popover with oldState and newState. |
The panel goes in the top layer, so it is not clipped by overflow: hidden and not affected by z-index anywhere on the page. Position it with Floating UI or CSS anchor positioning — the attribute itself places nothing.
See Web Components for loading i80.js.
0.1.0
Første i80-version (fork af upstream, se core/UPSTREAM.md).