Files
ditto.site/compiler/fixtures/menu-mount.html
2026-06-29 15:11:48 -07:00

66 lines
2.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mount-on-open menu fixture</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; }
header { display: flex; align-items: center; gap: 24px; height: 56px; padding: 0 24px; border-bottom: 1px solid #eee; }
.brand { font-weight: 700; }
nav { display: flex; gap: 8px; }
.trigger { background: none; border: 0; font: inherit; padding: 8px 12px; border-radius: 6px; cursor: pointer; color: #333; }
.trigger[aria-expanded="true"] { background: #eef2fd; color: #2b50d6; }
/* the panel is mounted into <body> on open (Radix-style portal) and removed on close */
.menu-panel { position: absolute; background: #fff; border: 1px solid #e2e2e2; border-radius: 12px; box-shadow: 0 12px 32px rgba(0,0,0,0.12); padding: 16px; width: 320px; display: grid; gap: 8px; }
.menu-panel a { display: block; padding: 10px 12px; border-radius: 8px; color: #222; text-decoration: none; }
.menu-panel a:hover { background: #f4f6fe; }
.menu-panel .label { font-size: 12px; color: #888; text-transform: uppercase; letter-spacing: .04em; padding: 4px 12px; }
main { padding: 48px 24px; }
</style>
</head>
<body>
<header>
<span class="brand">Acme</span>
<nav>
<button class="trigger" id="t-product" aria-haspopup="menu" aria-expanded="false" aria-controls="panel-product">Product</button>
<a class="trigger" href="/pricing">Pricing</a>
</nav>
</header>
<main>
<h1>Mount-on-open menu</h1>
<p>The Product menu mounts its panel into &lt;body&gt; on open and removes it on close.</p>
</main>
<script>
const t = document.getElementById('t-product');
let panel = null;
function open() {
if (panel) return;
panel = document.createElement('div');
panel.className = 'menu-panel';
panel.id = 'panel-product';
panel.setAttribute('role', 'menu');
const r = t.getBoundingClientRect();
panel.style.left = (r.left + window.scrollX) + 'px';
panel.style.top = (r.bottom + window.scrollY + 8) + 'px';
panel.innerHTML = '<div class="label">Build</div>' +
'<a href="/features">Features</a>' +
'<a href="/integrations">Integrations</a>' +
'<a href="/changelog">Changelog</a>' +
'<div class="label">Learn</div>' +
'<a href="/docs">Documentation</a>' +
'<a href="/guides">Guides</a>';
document.body.appendChild(panel);
t.setAttribute('aria-expanded', 'true');
}
function close() {
if (panel) { panel.remove(); panel = null; }
t.setAttribute('aria-expanded', 'false');
}
t.addEventListener('click', () => (t.getAttribute('aria-expanded') === 'true' ? close() : open()));
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') close(); });
</script>
</body>
</html>