For an AI

Popup

Anchored overlay: the panel follows its trigger and flips bottom → right → top → left so it stays on screen. Positioning is CSS, not a JS layout loop. This site’s Theme and Explore controls in the header are the same <Popup> — native popover, no overlay runtime on Chromium.

LIVE

<Popup> anchored

Follows the button (CSS anchor). Flip: bottom → right → top → left.

Modal docs

view!

view! {
    <Popup id="menu" positions="bottom right top left" dismissIfShown>
        <button slot="anchor" type="button">"Menu"</button>
        <div>
            <a href="/docs">"Docs"</a>
        </div>
    </Popup>
}

Trigger without a slot

If you omit slot="anchor", the first child is the opener. The framework forces type="button" so a trigger inside a form does not submit. Host style is concatenated with anchor-name, not replaced. Native toggle keeps aria-expanded in sync.

CSS that breaks the panel

Do not put position: relative or overflow: hidden on the popup panel (glass utilities often do). The top layer then fails hit-testing. .r-popup already sets position: absolute and overflow: visible.

What SSR emits

popovertarget + [popover=auto] + anchor-name / position-anchor / position-try-fallbacks. Chromium needs no overlay JS. Safari without CSS anchor loads /_resuma/ui.js (lazy) to flip with getBoundingClientRect.

Optional open signal

let open = signal(false);
view! {
    <Popup id="tip" open={open}>
        <button slot="anchor" type="button">"Tip"</button>
        <p>"Hello"</p>
    </Popup>
}

Programmatic

js! { __resuma.showPopup("menu"); }
    js! { __resuma.hidePopup("menu"); }

See also Modal (focus trap + stack) and portals (teleport only — not a dialog API).