Command palette

커맨드 팔레트

A global search box, usually opened with ⌘K, that finds and runs any command in the app just by typing.

Also known as: Quick switcherAction search⌘K menuSpotlight-style search
···
html
<div class="cpw">
  <div class="cprow"><span class="cpico">⌘K</span><input id="cpi" readonly placeholder="명령 검색…"></div>
  <ul class="cplist" id="cpl">
    <li>새 문서 만들기</li><li>파일 열기</li><li>테마 전환</li>
  </ul>
</div>
css
.cpw{width:min(230px,92%);background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:0 16px 34px rgba(0,0,0,.2);overflow:hidden}
.cprow{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line)}
.cpico{font-size:10px;font-weight:700;color:var(--muted);border:1px solid var(--line);border-radius:5px;padding:2px 5px}
#cpi{border:0;background:none;color:var(--fg);font-size:12px;flex:1;outline:none}
.cplist{list-style:none;margin:0;padding:5px}
.cplist li{padding:8px 10px;border-radius:7px;font-size:12px;color:var(--fg)}
.cplist li[hidden]{display:none}
.cplist li[data-hi]{background:var(--accent);color:#fff}
js
const input = document.getElementById('cpi'), items = [...document.querySelectorAll('.cplist li')];
const word = '새 문';
function filter(q) {
  let first = null;
  items.forEach((li) => {
    const match = !q || li.textContent.includes(q);
    li.hidden = !match; li.removeAttribute('data-hi');
    if (match && !first) first = li;
  });
  if (first) first.setAttribute('data-hi', '');
  return first;
}
filter('');
function loop() {
  input.value = ''; filter('');
  let i = 0;
  const type = setInterval(() => {
    i++; input.value = word.slice(0, i);
    const hit = filter(input.value);
    if (i >= word.length) {
      clearInterval(type);
      setTimeout(() => { if (hit) hit.style.transform = 'scale(.97)'; setTimeout(() => { items.forEach(li => li.style.transform = ''); setTimeout(loop, 1100); }, 260); }, 500);
    }
  }, 340);
}
loop();

It opens as a modal (role="dialog") containing a combobox+listbox pattern — the input points at the highlighted command via aria-activedescendant, arrow keys move, Enter runs it, Esc closes it. Most support fuzzy matching, so typing "newdoc" can still match "Create New Document."

The difference from a combobox is scope — a combobox is a narrow control for picking one value inside a form, while a command palette is global navigation across the whole app (navigate pages, change settings, run commands) and always opens as a modal. It shares "pick from a list" with a dropdown menu too, but the palette is an open list filtered by typed text rather than a fixed set of items.

Make sure the global shortcut (⌘K/Ctrl+K) doesn't collide with a browser or OS default first.