Overview

popup(content, options?) is an element directive — attach it to the anchor with ${popup(...)}. The panel uses position: fixed, repositions on scroll/resize, and escapes overflow: hidden ancestors.

Toggle mode (default): click the anchor to open/close; outside-click and Escape close automatically. Controlled mode: pass open as a boolean atom — you own open/close (no automatic outside-click / Escape).

For modals and hover tips, use mates-ui (Dialog, tooltip, tip) — they build on portal / popup.

Modes

Mode
open option
Behaviour
Toggle omit open Click anchor toggles. Outside-click + Escape close.
Controlled open: atom No click listener. You set the atom; wire dismiss yourself.

Quick reference

// Placement shorthand
html`<button ${popup(html`…`, 'bottom-start')}>Menu</button>`

Anchored dropdown with popup()

Attach popup() to the button. Pass an open atom for controlled visibility. The panel floats with position:fixed so it is never clipped by overflow:hidden containers.

import { html, atom, popup, renderApp } from 'mates';

const App = () => {
const open = atom(false);
const selected = atom('Option A');

const menu = html`
<div class="card card-body">
${['Option A','Option B','Option C'].map(opt => html`
<button class="btn-ghost btn-block m-t-10"
@click=${() => { selected.set(opt); open.set(false); }}>
${opt}${selected() === opt ? ' ✓' : ''}
</button>
`)}
</div>
`;

return () => html`
<button
class="btn-primary"
${popup(menu, { open, position: 'bottom-start', gap: 8 })}
@click=${() => open.set(v => !v)}
>
${selected()}
</button>
`;
};
renderApp(App, document.getElementById('app'));

Toggle mode (no open atom)

Omit open — click the anchor to toggle. Outside-click and Escape close automatically.

import { html, popup, renderApp } from 'mates';

const menu = html`
<div class="card card-body">
<button class="btn-ghost btn-block m-t-10">Item A</button>
<button class="btn-ghost btn-block m-t-10">Item B</button>
</div>
`;

const App = () => () => html`
<button class="btn-primary" ${popup(menu, 'bottom-start')}>
Toggle menu ▾
</button>
`;
renderApp(App, document.getElementById('app'));