A popover has an id. Any element with a data-ddi-popovertarget attribute set to that id toggles it.
---
import { Popover, Text } from "@dynamic-type/ddi/server";
---
<Text class="p:airy">
<p>
A popover has an id. Any element with a {" "}
<code>data-ddi-popovertarget</code> attribute set to that id toggles it.
</p>
{(<button data-ddi-popovertarget="example-popover">Hit me!</button>)}
</Text>
<Popover id="example-popover" class="bg drop-shadow p">
I am a popover
</Popover>Use the data-ddi-align property to set the position of the popover.
---
import { Popover, Text } from "@dynamic-type/ddi/server";
---
<Text class="p:airy">
<p>
Use the <code>data-ddi-align</code> property to set the position of the popover.
</p>
{
(
<button
data-ddi-popovertarget="example-popover-2"
data-ddi-align="top-center"
>
Hit me!
</button>
)
}
</Text>
<Popover id="example-popover-2" class="bg drop-shadow p">
I am a popover
</Popover>bottom-center opens the popover above the trigger, centered on it.
---
import { Popover, Text } from "@dynamic-type/ddi/server";
---
<Text class="p:airy">
<p>
<code>bottom-center</code> opens the popover above the trigger, centered
on it.
</p>
{
(
<button
data-ddi-popovertarget="example-popover-3"
data-ddi-align="bottom-center"
>
Hit me!
</button>
)
}
</Text>
<Popover id="example-popover-3" class="bg drop-shadow p">
I am a popover
</Popover>data-ddi-offset-x and data-ddi-offset-y nudge the popover away from its aligned position. They accept any CSS length, like20px, 1rem or -0.5em.
---
import { Popover, Text } from "@dynamic-type/ddi/server";
---
<Text class="p:airy">
<p>
<code>data-ddi-offset-x</code> and <code>data-ddi-offset-y</code> nudge the
popover away from its aligned position. They accept any CSS length, like
<code>20px</code>, <code>1rem</code> or <code>-0.5em</code>.
</p>
{
(
<button
data-ddi-popovertarget="example-popover-4"
data-ddi-offset-x="1rem"
data-ddi-offset-y="0.5rem"
>
Hit me!
</button>
)
}
</Text>
<Popover id="example-popover-4" class="bg drop-shadow p">
I am a popover
</Popover>Placing a popover against another element
By default a popover is placed against its trigger, using the trigger’s data-ddi-align and data-ddi-offset-*. Set data-ddi-popover-anchor="<id>" on the trigger to place it against that element instead, with that element’s align and offsets. Opening it also closes the popover the trigger sits in. CollapsibleMenu uses this so a folded item opens its popover from the overflow button.
A trigger with no box, for example one inside a closed popover, is placed against its nearest ancestor that has a box, not at the top-left of the screen.
ddi:popover-open reports the element it was placed against as detail.anchor, next to detail.trigger.
Rendered in the top layer
An open popover is shown in the top layer with the native Popover API (popover="manual"). It is placed against the viewport and never clipped, whatever its ancestors do. A transform, will-change: transform, filter, clip-path or overflow: hidden on an ancestor, such as an escaped ScrollRevealY, no longer moves or cuts it off. This applies to Bubble and the menus’ popovers too.
It stays where it is in the DOM. It inherits CSS, custom properties included, from its parent, and components that find their popover as a descendant still do. Don’t move popovers elsewhere to escape their ancestors.
data-ddi-open is the state. Write "true" or "false" to open or close a popover yourself. Only a trigger positions it. If the browser takes it out of the top layer, for example because it was removed or moved while open, the attribute goes back to "false". Closing a popover also closes the popovers inside it.
The browser’s own popover styles are undone, so it sizes as an ordinary position: fixed box. The trigger writes top and left; pin bottom yourself to make it stretch down to there, for example a panel that reaches the bottom of the screen.
Dismissal is unchanged: a click outside, a scroll or a resize closes it. No light-dismiss or Escape handling is added.
Stacking
z-index has no effect on an open popover. It paints above all ordinary content, whatever their z-index, and above the popovers opened before it. An element meant to cover an open popover must be in the top layer as well, such as a modal <dialog> or a popover opened after it.
A ::backdrop can dim the page behind a popover:
#filters::backdrop {
background: rgb(0 0 0 / 0.2);
}
Browsers without the Popover API show and hide the popover in place by display, as before.