No libraryTransitions
Native popover
A popover is not a dialog: nothing behind it is blocked, and the browser dismisses it on a click outside. The exit still plays while the element is in the top layer, which is the part a naive implementation gets wrong.
Every value the manifest allows on this host, single presets and the pairs that compose. The first is what this component ships with. Both stages are the same component, so anything that changes between them is the attribute.
Not modal, and light dismissed
Nothing behind this is blocked: scroll the page or press another button while it is open. Click outside or press Escape and the browser closes it, and the exit plays while the element is still in the top layer.
Not modal, and light dismissed
Nothing behind this is blocked: scroll the page or press another button while it is open. Click outside or press Escape and the browser closes it, and the exit plays while the element is still in the top layer.
:popover-open, and the top layer
[data-motion~="scale-fade"][popover]:not(:popover-open)
transition: opacity, scale, display, overlay
<div popover data-motion="scale-fade">
Where the attribute goes
The parts this demo composes, and the value each one carries. Everything inside an animated part is that part's content, so the tree stops there.
buttondivdata-motion="scale-fade"
Source
"use client"
import { useId } from "react"
import type { DemoProps } from "@/components/demos/props"
export function NativePopover({ motion }: DemoProps) {
const id = useId()
/* One anchor name per instance. The page mounts this demo twice, and two triggers sharing
a name would both resolve to whichever comes last in the DOM, so the control column's
popover would jump to the other column's button. useId is not a valid ident, hence the
scrub. */
const anchor = { "--anchor": `--pop-${id.replace(/[^a-z0-9]/gi, "")}` } as React.CSSProperties
return (
<>
<button type="button" className="btn pop__trigger" popoverTarget={id} style={anchor}>
Open popover
</button>
<div id={id} popover="auto" className="pop" data-motion={motion} style={anchor}>
<p className="panel__title">Not modal, and light dismissed</p>
<p className="panel__body">
Nothing behind this is blocked: scroll the page or press another button while it is
open. Click outside or press Escape and the browser closes it, and the exit plays
while the element is still in the top layer.
</p>
<div className="modal__actions">
<button
type="button"
className="btn btn--primary"
popoverTarget={id}
popoverTargetAction="hide"
>
Close
</button>
</div>
</div>
</>
)
}motion prop is the only difference between them.