Book a callGitHub5

It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.

Source
<style>
.odl-command-menu { box-sizing: border-box; inline-size: 100%; max-inline-size: 560px; background: var(--ds-color-surface-overlay); color: var(--ds-color-text-primary);
  border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-overlay); box-shadow: var(--ds-elevation-overlay); font: var(--ds-text-body-md); overflow: hidden; text-wrap: pretty; }
.odl-command-menu .odl-search { display: flex; align-items: center; gap: var(--ds-space-inline-sm); padding: 0 var(--ds-space-inset-lg); border-block-end: var(--ds-border-width-default) solid var(--ds-color-border-subtle); }
.odl-command-menu .odl-search svg { flex: none; inline-size: var(--ds-size-icon-md); block-size: var(--ds-size-icon-md); color: var(--ds-color-icon-subtle); }
.odl-command-menu input { flex: 1; min-inline-size: 0; block-size: var(--ds-size-control-lg); border: 0; background: transparent; color: inherit; font: var(--ds-text-body-lg); outline: none; }
.odl-command-menu input::placeholder { color: var(--ds-color-text-tertiary); }
.odl-command-menu .odl-search:has(input:focus-visible) { box-shadow: inset 0 calc(-1 * var(--ds-border-width-emphasis)) 0 var(--ds-color-border-focus); }
.odl-command-menu kbd { display: inline-grid; place-items: center; min-inline-size: var(--ds-space-20); padding: 0 var(--ds-space-4); border: var(--ds-border-width-default) solid var(--ds-color-border-subtle);
  border-radius: var(--ds-radius-detail); background: var(--ds-color-surface-raised); color: var(--ds-color-text-secondary); font: var(--ds-text-code-sm); }
.odl-command-menu [role="listbox"] { max-block-size: calc(var(--ds-size-row-md) * 9); overflow-y: auto; padding: var(--ds-space-inset-xs); }
.odl-command-menu .odl-group { padding: var(--ds-space-inset-sm) var(--ds-space-inset-sm) var(--ds-space-4); color: var(--ds-color-text-tertiary); font: var(--ds-text-label-md); }
.odl-command-menu [role="option"] { display: flex; align-items: center; gap: var(--ds-space-inline-sm); min-block-size: var(--ds-size-row-md); padding: 0 var(--ds-space-inset-sm);
  border-radius: var(--ds-radius-nested); cursor: pointer; }
.odl-command-menu [role="option"] svg { flex: none; inline-size: var(--ds-size-icon-md); block-size: var(--ds-size-icon-md); color: var(--ds-color-icon-subtle); }
.odl-command-menu [role="option"] span { flex: 1; min-inline-size: 0; }
.odl-command-menu [role="option"] small { color: var(--ds-color-text-tertiary); font: var(--ds-text-body-sm); }
.odl-command-menu [role="option"]:hover { background: var(--ds-color-bg-neutral-subtle); }
.odl-command-menu [role="option"][aria-selected="true"] { background: var(--ds-color-bg-accent-subtle); color: var(--ds-color-text-accent); }
.odl-command-menu [role="option"][aria-selected="true"] svg { color: var(--ds-color-icon-accent); }
.odl-command-menu [hidden] { display: none; }
.odl-command-menu .odl-empty { margin: 0; padding: var(--ds-space-inset-lg); text-align: center; color: var(--ds-color-text-secondary); }
.odl-command-menu footer { display: flex; flex-wrap: wrap; gap: var(--ds-space-inline-md); padding: var(--ds-space-inset-xs) var(--ds-space-inset-lg); border-block-start: var(--ds-border-width-default) solid var(--ds-color-border-subtle);
  background: var(--ds-color-surface-sunken); color: var(--ds-color-text-tertiary); font: var(--ds-text-label-md); }
.odl-command-menu footer span { display: inline-flex; align-items: center; gap: var(--ds-space-4); }
</style>
<div class="odl-command-menu" role="dialog" aria-label="Command menu">
  <div class="odl-search">
    <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="9" cy="9" r="5.5"/><path d="m13 13 4 4"/></svg>
    <input type="text" role="combobox" aria-expanded="true" aria-controls="odl-command-menu-list" aria-autocomplete="list" aria-label="Search commands" placeholder="Type a command or search" autocomplete="off">
    <kbd>Esc</kbd>
  </div>
  <div role="listbox" id="odl-command-menu-list" aria-label="Commands">
    <div class="odl-group" role="presentation">Actions</div>
    <div role="option" id="odl-cm-1" aria-selected="true"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg><span>New invoice</span><kbd>N</kbd></div>
    <div role="option" id="odl-cm-2" aria-selected="false"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M3 8h8M8 4l4 4-4 4"/></svg><span>Record a receipt</span><kbd>R</kbd></div>
    <div role="option" id="odl-cm-3" aria-selected="false"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M8 2.5v8M4.5 7 8 10.5 11.5 7M3 13.5h10"/></svg><span>Export ledger as CSV</span></div>
    <div class="odl-group" role="presentation">Go to</div>
    <div role="option" id="odl-cm-4" aria-selected="false"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><rect x="3" y="2.5" width="10" height="11" rx="1.5"/><path d="M5.5 6h5M5.5 9h3"/></svg><span>Receipts <small>192 to match</small></span></div>
    <div role="option" id="odl-cm-5" aria-selected="false"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="8" cy="6" r="2.5"/><path d="M3.5 13.5a4.5 4.5 0 0 1 9 0"/></svg><span>Customers</span></div>
    <div role="option" id="odl-cm-6" aria-selected="false"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="8" cy="8" r="2"/><path d="M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2M3.4 3.4l1.4 1.4M11.2 11.2l1.4 1.4M3.4 12.6l1.4-1.4M11.2 4.8l1.4-1.4"/></svg><span>Settings</span><kbd>,</kbd></div>
    <p class="odl-empty" hidden>No commands match. Try a shorter word.</p>
  </div>
  <footer><span><kbd>↑</kbd><kbd>↓</kbd> move</span><span><kbd>↵</kbd> open</span><span><kbd>Esc</kbd> close</span></footer>
</div>
<script>
document.querySelectorAll(".odl-command-menu").forEach((root) => {
  if (root.dataset.odlReady) return; // wire once, even if the file is pasted twice
  root.dataset.odlReady = "1";
  const list = root.querySelector('[role="listbox"]');
  const keepInView = (o) => { // scroll the list only, never the page
    const top = o.offsetTop - list.offsetTop, bottom = top + o.offsetHeight;
    if (top < list.scrollTop) list.scrollTop = top; else if (bottom > list.scrollTop + list.clientHeight) list.scrollTop = bottom - list.clientHeight;
  };
  const input = root.querySelector("input"), opts = [...root.querySelectorAll('[role="option"]')], empty = root.querySelector(".odl-empty");
  const visible = () => opts.filter((o) => !o.hidden);
  const pick = (o, scroll) => { opts.forEach((x) => x.setAttribute("aria-selected", x === o ? "true" : "false")); if (o) { input.setAttribute("aria-activedescendant", o.id); if (scroll) keepInView(o); } };
  pick(opts[0]);
  input.addEventListener("input", () => {
    const q = input.value.trim().toLowerCase();
    opts.forEach((o) => { o.hidden = !!q && !o.textContent.toLowerCase().includes(q); });
    root.querySelectorAll(".odl-group").forEach((g) => { let n = g.nextElementSibling, any = false; while (n && !n.classList.contains("odl-group")) { if (n.getAttribute("role") === "option" && !n.hidden) any = true; n = n.nextElementSibling; } g.hidden = !any; });
    empty.hidden = visible().length > 0; pick(visible()[0]);
  });
  input.addEventListener("keydown", (e) => {
    const v = visible(), i = v.findIndex((o) => o.getAttribute("aria-selected") === "true");
    if (e.key === "ArrowDown" || e.key === "ArrowUp") { e.preventDefault(); pick(v[(i + (e.key === "ArrowDown" ? 1 : v.length - 1)) % v.length], true); }
  });
  opts.forEach((o) => o.addEventListener("mousemove", () => pick(o)));
});
</script>

More like this

B2BQuiet · CRM

Page header with tabs

The top of a record page: breadcrumb, title with a favourite star and summary chips, two actions, and an underline tab bar with counts that scrolls on its own when narrow.

B2BDense · Any product

Pagination

The footer under a long table: how many rows are showing, rows per page, and previous, next and page numbers that collapse to "Page 3 of 49" when narrow.

B2BFriendly · SaaS

Setup checklist

A short list of first steps with progress: what is done, the one step to do now with its time and a way to skip, and what comes next.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free