Open demo

CSS code

HTML
<button class="cmd-launch" type="button" aria-haspopup="dialog" aria-controls="cmd" aria-keyshortcuts="Control+K Meta+K"><span aria-hidden="true">🔍</span> Search or jump to… <kbd aria-hidden="true">⌘K</kbd></button>
<dialog class="cmd" id="cmd" aria-label="Command palette">
  <div class="cmd-inp"><span aria-hidden="true">🔍</span><input type="text" role="combobox" aria-label="Type a command or search" aria-expanded="true" aria-controls="cmd-list" aria-autocomplete="list" placeholder="Type a command or search…" autocomplete="off" spellcheck="false"><kbd aria-hidden="true">ESC</kbd></div>
  <div class="cmd-list" id="cmd-list" role="listbox" aria-label="Commands" tabindex="-1">
    <div role="group" aria-labelledby="cmd-g1">
      <p class="cmd-gh" id="cmd-g1">Navigation</p>
      <div class="cmd-it" role="option" id="cmd-o1" aria-selected="true" data-href="#dashboard"><span aria-hidden="true">🏠</span> Go to dashboard <span class="cmd-k" aria-hidden="true">G D</span></div>
      <div class="cmd-it" role="option" id="cmd-o2" aria-selected="false" data-href="#projects"><span aria-hidden="true">📁</span> Open project… <span class="cmd-k" aria-hidden="true">G P</span></div>
      <div class="cmd-it" role="option" id="cmd-o3" aria-selected="false" data-href="#team"><span aria-hidden="true">👥</span> View team <span class="cmd-k" aria-hidden="true">G T</span></div>
    </div>
    <div role="group" aria-labelledby="cmd-g2">
      <p class="cmd-gh" id="cmd-g2">Actions</p>
      <div class="cmd-it" role="option" id="cmd-o4" aria-selected="false"><span aria-hidden="true">➕</span> Create new document <span class="cmd-k" aria-hidden="true">⌘N</span></div>
      <div class="cmd-it" role="option" id="cmd-o5" aria-selected="false"><span aria-hidden="true">📤</span> Share current page <span class="cmd-k" aria-hidden="true">⌘⇧S</span></div>
      <div class="cmd-it" role="option" id="cmd-o6" aria-selected="false"><span aria-hidden="true">🌓</span> Toggle dark mode <span class="cmd-k" aria-hidden="true">⌘⇧L</span></div>
    </div>
    <div role="group" aria-labelledby="cmd-g3">
      <p class="cmd-gh" id="cmd-g3">Help</p>
      <div class="cmd-it" role="option" id="cmd-o7" aria-selected="false" data-href="#docs"><span aria-hidden="true">📖</span> Documentation</div>
      <div class="cmd-it" role="option" id="cmd-o8" aria-selected="false" data-href="#support"><span aria-hidden="true">💬</span> Contact support</div>
    </div>
  </div>
  <p class="cmd-empty" role="status"></p>
</dialog>
CSS
/* Command palette: a modal <dialog> holding a combobox input and a grouped listbox of commands.
   Opens from the launcher button or Ctrl/⌘+K; Esc closes it and returns focus to the launcher. */
.cmd-launch{display:flex;align-items:center;gap:12px;width:100%;max-width:520px;padding:14px 18px;border:1px solid #2f3650;border-radius:14px;background:rgba(23,27,40,.7);color:#a3acc8;font:inherit;font-size:.95rem;text-align:left;cursor:pointer}
.cmd-launch:hover{border-color:#414a6b;color:#e6e9f4}
.cmd-launch:focus-visible{outline:2px solid #818cf8;outline-offset:2px}
.cmd-launch kbd{margin-left:auto}
.cmd{width:calc(100% - 32px);max-width:520px;margin:80px auto 0;padding:0;background:rgba(23,27,40,.92);color:#e6e9f4;border:1px solid #2f3650;border-radius:16px;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 34px 70px -20px rgba(0,0,0,.6);overflow:hidden}
.cmd[open]{animation:cmd-in .16s ease}
@keyframes cmd-in{from{opacity:0;transform:translateY(-6px) scale(.98)}}
.cmd::backdrop{background:rgba(2,6,23,.35)}
.cmd-inp{display:flex;align-items:center;gap:12px;padding:16px 18px;border-bottom:1px solid #262d44}
.cmd-inp:focus-within{box-shadow:inset 0 -2px 0 #818cf8}
.cmd-inp input{flex:1;min-width:0;border:0;background:none;color:#fff;font:inherit;font-size:1rem;outline:none}
.cmd-inp input::placeholder{color:#8a93ad}
.cmd kbd,.cmd-launch kbd{font-family:inherit;font-size:.68rem;background:#262d44;color:#a3acc8;border-radius:6px;padding:3px 8px}
.cmd-list{padding:8px;max-height:min(440px,calc(100vh - 220px));overflow:auto}
.cmd-gh{margin:0;font-size:.66rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#8a93ad;padding:10px 12px 5px}
.cmd-it{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:10px;font-size:.9rem;font-weight:600;color:#c3cbdf;cursor:pointer}
.cmd-it[aria-selected="true"]{background:#242c47;color:#fff}
.cmd-k{margin-left:auto;font-size:.66rem;color:#8a93ad}
.cmd-it[aria-selected="true"] .cmd-k{color:#a3acc8}
.cmd-empty{margin:0;padding:8px 20px 20px;font-size:.66rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#8a93ad}
.cmd-empty:empty,.cmd [hidden]{display:none!important}
@media (prefers-reduced-motion:reduce){.cmd[open]{animation:none}}
JavaScript
/* Combobox + listbox (WAI-ARIA pattern) inside a modal dialog. Typing filters the commands and hides empty groups;
   ArrowUp/ArrowDown move the highlighted option (aria-activedescendant), Enter or a click runs it and closes the palette.
   Commands with data-href navigate; wire the others to your own handlers. */
(() => {
  const dlg = document.getElementById('cmd'); if (!dlg) return;
  const launch = document.querySelector('[aria-controls="cmd"]');
  const input = dlg.querySelector('[role="combobox"]'), list = dlg.querySelector('[role="listbox"]'), empty = dlg.querySelector('[role="status"]');
  const opts = [...list.querySelectorAll('[role="option"]')];
  const label = o => [...o.childNodes].filter(n => n.nodeType === 3).map(n => n.textContent).join('').trim().toLowerCase();
  const shown = () => opts.filter(o => !o.hidden);
  let active = null;
  const select = o => {
    opts.forEach(x => x.setAttribute('aria-selected', x === o));
    active = o || null;
    if (o) { input.setAttribute('aria-activedescendant', o.id); o.scrollIntoView({ block: 'nearest' }); }
    else input.removeAttribute('aria-activedescendant');
  };
  const filter = () => {
    const q = input.value.trim().toLowerCase();
    opts.forEach(o => { o.hidden = !label(o).includes(q); });
    list.querySelectorAll('[role="group"]').forEach(g => { g.hidden = !g.querySelector('[role="option"]:not([hidden])'); });
    const v = shown();
    select(v[0]);
    empty.textContent = v.length ? '' : 'No results';
  };
  const open = () => { input.value = ''; filter(); dlg.showModal(); input.focus(); };
  const run = o => { if (!o) return; dlg.close(); if (o.dataset.href) location.assign(o.dataset.href); };

  launch.addEventListener('click', open);
  input.addEventListener('input', filter);
  input.addEventListener('keydown', e => {
    const v = shown(), i = v.indexOf(active);
    if (e.key === 'ArrowDown') { e.preventDefault(); select(v[(i + 1) % v.length]); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); select(v.at(i <= 0 ? -1 : i - 1)); }
    else if (e.key === 'Enter') { e.preventDefault(); run(active); }
  });
  list.addEventListener('click', e => run(e.target.closest('[role="option"]')));
  list.addEventListener('mousemove', e => { const o = e.target.closest('[role="option"]'); if (o && o !== active) select(o); });
  dlg.addEventListener('click', e => { if (e.target === dlg) dlg.close(); }); // a click on the backdrop
  dlg.addEventListener('close', () => launch.focus());
  document.addEventListener('keydown', e => {
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); dlg.open ? dlg.close() : open(); }
  });
})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<button class="btn cmd-launch" type="button" data-bs-toggle="modal" data-bs-target="#cmd" aria-haspopup="dialog" aria-keyshortcuts="Control+K Meta+K"><span aria-hidden="true">🔍</span> Search or jump to… <kbd aria-hidden="true">⌘K</kbd></button>
<div class="modal fade cmd" id="cmd" tabindex="-1" role="dialog" aria-label="Command palette" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="cmd-inp"><span aria-hidden="true">🔍</span><input class="form-control" type="text" role="combobox" aria-label="Type a command or search" aria-expanded="true" aria-controls="cmd-list" aria-autocomplete="list" placeholder="Type a command or search…" autocomplete="off" spellcheck="false"><kbd aria-hidden="true">ESC</kbd></div>
      <div class="list-group list-group-flush" id="cmd-list" role="listbox" aria-label="Commands" tabindex="-1">
        <div role="group" aria-labelledby="cmd-g1">
          <p class="cmd-gh" id="cmd-g1">Navigation</p>
          <div class="list-group-item" role="option" id="cmd-o1" aria-selected="true" data-href="#dashboard"><span aria-hidden="true">🏠</span> Go to dashboard <span class="cmd-k" aria-hidden="true">G D</span></div>
          <div class="list-group-item" role="option" id="cmd-o2" aria-selected="false" data-href="#projects"><span aria-hidden="true">📁</span> Open project… <span class="cmd-k" aria-hidden="true">G P</span></div>
          <div class="list-group-item" role="option" id="cmd-o3" aria-selected="false" data-href="#team"><span aria-hidden="true">👥</span> View team <span class="cmd-k" aria-hidden="true">G T</span></div>
        </div>
        <div role="group" aria-labelledby="cmd-g2">
          <p class="cmd-gh" id="cmd-g2">Actions</p>
          <div class="list-group-item" role="option" id="cmd-o4" aria-selected="false"><span aria-hidden="true">➕</span> Create new document <span class="cmd-k" aria-hidden="true">⌘N</span></div>
          <div class="list-group-item" role="option" id="cmd-o5" aria-selected="false"><span aria-hidden="true">📤</span> Share current page <span class="cmd-k" aria-hidden="true">⌘⇧S</span></div>
          <div class="list-group-item" role="option" id="cmd-o6" aria-selected="false"><span aria-hidden="true">🌓</span> Toggle dark mode <span class="cmd-k" aria-hidden="true">⌘⇧L</span></div>
        </div>
        <div role="group" aria-labelledby="cmd-g3">
          <p class="cmd-gh" id="cmd-g3">Help</p>
          <div class="list-group-item" role="option" id="cmd-o7" aria-selected="false" data-href="#docs"><span aria-hidden="true">📖</span> Documentation</div>
          <div class="list-group-item" role="option" id="cmd-o8" aria-selected="false" data-href="#support"><span aria-hidden="true">💬</span> Contact support</div>
        </div>
      </div>
      <p class="cmd-empty" role="status"></p>
    </div>
  </div>
</div>
CSS
/* Bootstrap .modal holding a combobox input and a .list-group used as a grouped listbox.
   The Modal plugin traps focus, closes on Esc or a backdrop click and hands focus back to the launcher. */
.cmd-launch{--bs-btn-padding-x:18px;--bs-btn-padding-y:14px;--bs-btn-font-size:.95rem;--bs-btn-border-radius:14px;--bs-btn-color:#a3acc8;--bs-btn-bg:rgba(23,27,40,.7);--bs-btn-border-color:#2f3650;
  --bs-btn-hover-color:#e6e9f4;--bs-btn-hover-bg:rgba(23,27,40,.7);--bs-btn-hover-border-color:#414a6b;--bs-btn-active-color:#e6e9f4;--bs-btn-active-bg:rgba(23,27,40,.7);--bs-btn-active-border-color:#414a6b;
  display:flex;align-items:center;gap:12px;width:100%;max-width:520px;text-align:left}
.cmd-launch:focus-visible{outline:2px solid #818cf8;outline-offset:2px;box-shadow:none}
.cmd-launch kbd{margin-left:auto}
.cmd{--bs-modal-width:520px;--bs-modal-margin:16px;--bs-modal-bg:rgba(23,27,40,.92);--bs-modal-color:#e6e9f4;--bs-modal-border-color:#2f3650;--bs-modal-border-radius:16px;--bs-modal-inner-border-radius:15px;--bs-modal-box-shadow:0 34px 70px -20px rgba(0,0,0,.6)}
.cmd .modal-dialog{margin-top:80px}
.cmd .modal-content{overflow:hidden;box-shadow:var(--bs-modal-box-shadow);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.modal-backdrop{--bs-backdrop-bg:#020617;--bs-backdrop-opacity:.35}
.cmd-inp{display:flex;align-items:center;gap:12px;padding:16px 18px;border-bottom:1px solid #262d44}
.cmd-inp:focus-within{box-shadow:inset 0 -2px 0 #818cf8}
.cmd-inp .form-control{flex:1;min-width:0;padding:0;border:0;border-radius:0;background:none;color:#fff;font-size:1rem;box-shadow:none}
.cmd-inp .form-control::placeholder{color:#8a93ad}
.cmd kbd,.cmd-launch kbd{font-family:inherit;font-size:.68rem;background:#262d44;color:#a3acc8;border-radius:6px;padding:3px 8px}
.cmd .list-group{--bs-list-group-bg:transparent;--bs-list-group-color:#c3cbdf;--bs-list-group-border-width:0;--bs-list-group-item-padding-x:12px;--bs-list-group-item-padding-y:10px;
  padding:8px;max-height:min(440px,calc(100vh - 220px));overflow:auto}
.cmd .list-group-item{display:flex;align-items:center;gap:12px;border-radius:10px;font-size:.9rem;font-weight:600;cursor:pointer}
.cmd .list-group-item[aria-selected="true"]{background:#242c47;color:#fff}
.cmd-gh{margin:0;font-size:.66rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#8a93ad;padding:10px 12px 5px}
.cmd-k{margin-left:auto;font-size:.66rem;color:#8a93ad}
.cmd .list-group-item[aria-selected="true"] .cmd-k{color:#a3acc8}
.cmd-empty{margin:0;padding:8px 20px 20px;font-size:.66rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#8a93ad}
.cmd-empty:empty,.cmd [hidden]{display:none!important}
@media (prefers-reduced-motion:reduce){.cmd.fade .modal-dialog{transition:none}}
JavaScript
/* Combobox + listbox (WAI-ARIA pattern) inside a Bootstrap modal. Typing filters the commands and hides empty groups;
   ArrowUp/ArrowDown move the highlighted option (aria-activedescendant), Enter or a click runs it and closes the palette.
   Ctrl/⌘+K toggles it. Commands with data-href navigate; wire the others to your own handlers. */
(() => {
  const el = document.getElementById('cmd'); if (!el) return;
  const modal = bootstrap.Modal.getOrCreateInstance(el);
  const launch = document.querySelector('[data-bs-target="#cmd"]');
  const input = el.querySelector('[role="combobox"]'), list = el.querySelector('[role="listbox"]'), empty = el.querySelector('[role="status"]');
  const opts = [...list.querySelectorAll('[role="option"]')];
  const label = o => [...o.childNodes].filter(n => n.nodeType === 3).map(n => n.textContent).join('').trim().toLowerCase();
  const shown = () => opts.filter(o => !o.hidden);
  let active = null, pending = null;
  const select = o => {
    opts.forEach(x => x.setAttribute('aria-selected', x === o));
    active = o || null;
    if (o) { input.setAttribute('aria-activedescendant', o.id); o.scrollIntoView({ block: 'nearest' }); }
    else input.removeAttribute('aria-activedescendant');
  };
  const filter = () => {
    const q = input.value.trim().toLowerCase();
    opts.forEach(o => { o.hidden = !label(o).includes(q); });
    list.querySelectorAll('[role="group"]').forEach(g => { g.hidden = !g.querySelector('[role="option"]:not([hidden])'); });
    const v = shown();
    select(v[0]);
    empty.textContent = v.length ? '' : 'No results';
  };
  const run = o => { if (!o) return; pending = o.dataset.href; modal.hide(); };

  el.addEventListener('show.bs.modal', () => { input.value = ''; filter(); });
  el.addEventListener('shown.bs.modal', () => input.focus());
  el.addEventListener('hidden.bs.modal', () => { launch.focus(); if (pending) location.assign(pending); pending = null; });
  input.addEventListener('input', filter);
  input.addEventListener('keydown', e => {
    const v = shown(), i = v.indexOf(active);
    if (e.key === 'ArrowDown') { e.preventDefault(); select(v[(i + 1) % v.length]); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); select(v.at(i <= 0 ? -1 : i - 1)); }
    else if (e.key === 'Enter') { e.preventDefault(); run(active); }
  });
  list.addEventListener('click', e => run(e.target.closest('[role="option"]')));
  list.addEventListener('mousemove', e => { const o = e.target.closest('[role="option"]'); if (o && o !== active) select(o); });
  document.addEventListener('keydown', e => {
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); modal.toggle(); }
  });
})();

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<button class="cmd-launch flex w-full max-w-[520px] cursor-pointer items-center gap-3 rounded-[14px] border border-cmd-line bg-[rgba(23,27,40,.7)] px-[18px] py-3.5 text-left text-[.95rem] text-cmd-soft hover:border-[#414a6b] hover:text-[#e6e9f4] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cmd-accent" type="button" aria-haspopup="dialog" aria-controls="cmd" aria-keyshortcuts="Control+K Meta+K"><span aria-hidden="true">🔍</span> Search or jump to… <kbd class="ml-auto rounded-md bg-cmd-rule px-2 py-[3px] font-[inherit] text-[.68rem] text-cmd-soft" aria-hidden="true">⌘K</kbd></button>
<dialog class="mx-auto mt-20 w-[calc(100%-32px)] max-w-[520px] overflow-hidden rounded-2xl border border-cmd-line bg-cmd-panel p-0 text-[#e6e9f4] shadow-[0_34px_70px_-20px_rgba(0,0,0,.6)] backdrop-blur-[14px] backdrop:bg-[rgba(2,6,23,.35)] open:animate-cmd-in motion-reduce:animate-none" id="cmd" aria-label="Command palette">
  <div class="flex items-center gap-3 border-b border-cmd-rule px-[18px] py-4 focus-within:shadow-[inset_0_-2px_0_var(--color-cmd-accent)]"><span aria-hidden="true">🔍</span><input class="min-w-0 flex-1 bg-transparent text-base text-white outline-none placeholder:text-cmd-muted" type="text" role="combobox" aria-label="Type a command or search" aria-expanded="true" aria-controls="cmd-list" aria-autocomplete="list" placeholder="Type a command or search…" autocomplete="off" spellcheck="false"><kbd class="rounded-md bg-cmd-rule px-2 py-[3px] font-[inherit] text-[.68rem] text-cmd-soft" aria-hidden="true">ESC</kbd></div>
  <div class="max-h-[min(440px,calc(100vh-220px))] overflow-auto p-2" id="cmd-list" role="listbox" aria-label="Commands" tabindex="-1">
    <div role="group" aria-labelledby="cmd-g1">
      <p class="px-3 pt-2.5 pb-[5px] text-[.66rem] font-extrabold tracking-[.1em] text-cmd-muted uppercase" id="cmd-g1">Navigation</p>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o1" aria-selected="true" data-href="#dashboard"><span aria-hidden="true">🏠</span> Go to dashboard <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">G D</span></div>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o2" aria-selected="false" data-href="#projects"><span aria-hidden="true">📁</span> Open project… <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">G P</span></div>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o3" aria-selected="false" data-href="#team"><span aria-hidden="true">👥</span> View team <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">G T</span></div>
    </div>
    <div role="group" aria-labelledby="cmd-g2">
      <p class="px-3 pt-2.5 pb-[5px] text-[.66rem] font-extrabold tracking-[.1em] text-cmd-muted uppercase" id="cmd-g2">Actions</p>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o4" aria-selected="false"><span aria-hidden="true">➕</span> Create new document <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">⌘N</span></div>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o5" aria-selected="false"><span aria-hidden="true">📤</span> Share current page <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">⌘⇧S</span></div>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o6" aria-selected="false"><span aria-hidden="true">🌓</span> Toggle dark mode <span class="ml-auto text-[.66rem] text-cmd-muted group-aria-selected:text-cmd-soft" aria-hidden="true">⌘⇧L</span></div>
    </div>
    <div role="group" aria-labelledby="cmd-g3">
      <p class="px-3 pt-2.5 pb-[5px] text-[.66rem] font-extrabold tracking-[.1em] text-cmd-muted uppercase" id="cmd-g3">Help</p>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o7" aria-selected="false" data-href="#docs"><span aria-hidden="true">📖</span> Documentation</div>
      <div class="group flex cursor-pointer items-center gap-3 rounded-[10px] px-3 py-2.5 text-[.9rem] font-semibold text-[#c3cbdf] aria-selected:bg-cmd-sel aria-selected:text-white" role="option" id="cmd-o8" aria-selected="false" data-href="#support"><span aria-hidden="true">💬</span> Contact support</div>
    </div>
  </div>
  <p class="px-5 pt-2 pb-5 text-[.66rem] font-extrabold tracking-[.1em] text-cmd-muted uppercase empty:hidden" role="status"></p>
</dialog>
CSS
@theme {
  --color-cmd-panel: rgba(23,27,40,.92);
  --color-cmd-line: #2f3650;
  --color-cmd-rule: #262d44;
  --color-cmd-muted: #8a93ad;
  --color-cmd-soft: #a3acc8;
  --color-cmd-sel: #242c47;
  --color-cmd-accent: #818cf8;
  --animate-cmd-in: cmd-in .16s ease;
  @keyframes cmd-in { from { opacity: 0; transform: translateY(-6px) scale(.98); } }
}
JavaScript
/* Combobox + listbox (WAI-ARIA pattern) inside a modal dialog. Typing filters the commands and hides empty groups;
   ArrowUp/ArrowDown move the highlighted option (aria-activedescendant), Enter or a click runs it and closes the palette.
   Commands with data-href navigate; wire the others to your own handlers. */
(() => {
  const dlg = document.getElementById('cmd'); if (!dlg) return;
  const launch = document.querySelector('[aria-controls="cmd"]');
  const input = dlg.querySelector('[role="combobox"]'), list = dlg.querySelector('[role="listbox"]'), empty = dlg.querySelector('[role="status"]');
  const opts = [...list.querySelectorAll('[role="option"]')];
  const label = o => [...o.childNodes].filter(n => n.nodeType === 3).map(n => n.textContent).join('').trim().toLowerCase();
  const shown = () => opts.filter(o => !o.hidden);
  let active = null;
  const select = o => {
    opts.forEach(x => x.setAttribute('aria-selected', x === o));
    active = o || null;
    if (o) { input.setAttribute('aria-activedescendant', o.id); o.scrollIntoView({ block: 'nearest' }); }
    else input.removeAttribute('aria-activedescendant');
  };
  const filter = () => {
    const q = input.value.trim().toLowerCase();
    opts.forEach(o => { o.hidden = !label(o).includes(q); });
    list.querySelectorAll('[role="group"]').forEach(g => { g.hidden = !g.querySelector('[role="option"]:not([hidden])'); });
    const v = shown();
    select(v[0]);
    empty.textContent = v.length ? '' : 'No results';
  };
  const open = () => { input.value = ''; filter(); dlg.showModal(); input.focus(); };
  const run = o => { if (!o) return; dlg.close(); if (o.dataset.href) location.assign(o.dataset.href); };

  launch.addEventListener('click', open);
  input.addEventListener('input', filter);
  input.addEventListener('keydown', e => {
    const v = shown(), i = v.indexOf(active);
    if (e.key === 'ArrowDown') { e.preventDefault(); select(v[(i + 1) % v.length]); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); select(v.at(i <= 0 ? -1 : i - 1)); }
    else if (e.key === 'Enter') { e.preventDefault(); run(active); }
  });
  list.addEventListener('click', e => run(e.target.closest('[role="option"]')));
  list.addEventListener('mousemove', e => { const o = e.target.closest('[role="option"]'); if (o && o !== active) select(o); });
  dlg.addEventListener('click', e => { if (e.target === dlg) dlg.close(); }); // a click on the backdrop
  dlg.addEventListener('close', () => launch.focus());
  document.addEventListener('keydown', e => {
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); dlg.open ? dlg.close() : open(); }
  });
})();

About this set

A dark command palette of the kind opened with Ctrl+K or Cmd+K in modern apps. A launcher button reading Search or jump to opens a frosted panel with a search field and commands in three groups, Navigation, Actions and Help, each with an emoji and an optional shortcut hint. Typing filters the list as you go, empty groups disappear and a No results line appears when nothing matches. Use it to give power users one place to reach every page and action without hunting through menus. The panel is a modal dialog, so the rest of the page is inert while it is open, Esc closes it and focus returns to the launcher. Inside, it follows the WAI-ARIA combobox pattern: the input has role=”combobox” and controls a grouped listbox, and the arrow keys move the highlighted option through aria-activedescendant while focus stays in the input. Enter or a click runs the command and closes the palette. The plain CSS and Tailwind versions use the native dialog element; the Bootstrap version uses .modal with the Modal plugin and a .list-group for the options.

What’s included

  • Opens from a launcher button or Ctrl+K / Cmd+K
  • Live filtering that hides empty groups
  • Arrow-key highlighting with aria-activedescendant
  • Enter or click runs a command and closes the palette
  • Modal dialog that returns focus to the launcher

Accessibility

The palette is a modal dialog named Command palette. Its input is a labelled combobox that controls a listbox named Commands, with each group named by its heading, and a status region announces No results. Focus stays in the input while the arrow keys move the highlight, Esc closes the dialog and focus returns to the launcher, which shows a 2px indigo outline. The open animation is removed under prefers-reduced-motion.

Customise it

Change the panel, border and highlight colours in .cmd and .cmd-it (plain CSS), the --bs-modal-* and --bs-list-group-* variables (Bootstrap) or the --color-cmd-* theme colours (Tailwind). Add commands as options; data-href makes one navigate. The shortcut hints shown next to items are labels only; connect them to your own key handlers.