webdevpuneet.com

Command Palette — Free HTML CSS JS Cmd+K Snippet

Command Palette · Modals · Plain HTML, CSS & JS · Live preview

CategoryModals

Copy & paste

Source Code

<div class="page">
  <p class="hint">Press <kbd>⌘K</kbd> or <kbd>Ctrl+K</kbd></p>
  <button class="open-btn" onclick="openPalette()">Open Command Palette <kbd>⌘K</kbd></button>
</div>
<div class="overlay" id="overlay" onclick="closePalette()"></div>
<div class="palette" id="palette" role="dialog" aria-modal="true">
  <div class="search-row">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
    <input id="cmd-q" class="cmd-input" placeholder="Search commands…" oninput="filter(this.value)" autocomplete="off" />
    <kbd class="esc-key" onclick="closePalette()">ESC</kbd>
  </div>
  <div id="cmd-list" class="cmd-list"></div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Cmd+K and Ctrl+K shortcut opens the palette via document keydown listener
Substring filter on name and description — searches both fields simultaneously
Grouped results by group field with group label headers
Arrow key navigation: ArrowDown/Up calls setActive() + scrollIntoView
Enter runs the active command; ESC closes the palette
backdrop-filter blur overlay with scale+opacity open animation
data-idx attributes allow onclick delegation to individual items
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Command Palette — Cmd+K Shortcut, Grouped Commands, Fuzzy Search & Keyboard Nav

Screenshot of the Command Palette snippet rendered live

A command palette is a searchable list of application actions triggered by a keyboard shortcut — typically Cmd+K or Ctrl+K. Popularised by VS Code and Linear, it is now a standard power-user feature in developer tools, dashboards, and productivity apps. It replaces deep menu hierarchies with a single search interface: type a few characters and instantly find any action.

The COMMANDS data structure

Commands are plain JS objects with group, icon, name, desc, and shortcut fields. The render(cmds) function groups them by the group field and renders each group with a label and its items. Adding new commands is as simple as adding an object to the array.

The search/filter function

filter(q) converts the query to lowercase and calls COMMANDS.filter(c => c.name.toLowerCase().includes(lq) || c.desc.toLowerCase().includes(lq)). This searches both name and description — typing "dashboard" finds commands named "Open Dashboard" and commands with "dashboard" in their description. Passing the result to render() re-builds the list.

Keyboard navigation

A keydown listener on the input catches ArrowDown, ArrowUp, Enter, and Escape. Arrow keys call setActive(i) which removes .active from all items, adds it to the target item, and calls scrollIntoView({ block: 'nearest' }) so the active item is always visible. Enter calls pick(activeIdx) to execute the command. Escape calls closePalette().

Opening and closing

document.addEventListener('keydown', e => { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); openPalette(); } }) wires the Cmd+K shortcut. openPalette() adds .show to the overlay and palette and focuses the search input with a 50ms delay (allowing the CSS transition to start first). closePalette() removes .show from both.

Replacing alert() with real actions

The pick(i) function currently calls alert(). Replace it with a switch statement or a map from command name to handler function to execute real actions.

Keyboard shortcut capture

The Cmd+K / Ctrl+K listener checks: if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); openPalette(); }. e.preventDefault() stops the browser's default Cmd+K action (some browsers map this to a bookmark or search action). The listener is attached to document once on component mount and remains active globally while the page is open.

The fuzzy search algorithm

The search filters commands by checking if the query string is a substring of the command name or description: cmd.name.toLowerCase().includes(q) || cmd.desc.toLowerCase().includes(q). For a true fuzzy match (allowing out-of-order character matching), replace includes with a character-order test: const chars = [...q]; let idx = 0; return name.split('').some(c => c === chars[idx] && ++idx) && idx === chars.length. This matches "cmpl" to "command palette".

Arrow key navigation

The keydown handler tracks selectedIndex state. ArrowDown increments it (wrapping at the list end); ArrowUp decrements (wrapping to the end). The selected command gets a highlighted background. Enter triggers the selected command's action and closes the palette. The selectedIndex is reset to 0 on each new search query.

Step by step

How to Use

  1. 1
    Press Cmd+K in the previewClick inside the preview and press Cmd+K (or Ctrl+K) to open the palette. Or click the "Open palette" button.
  2. 2
    Type to searchType any word to filter commands by name or description. The list filters in real time as you type.
  3. 3
    Navigate with arrow keys and EnterUse ArrowDown/ArrowUp to move between commands. Press Enter to run the selected command. Press ESC to close.
  4. 4
    Add your own commandsIn the JS panel, add objects to the COMMANDS array: { group: "My Group", icon: "⭐", name: "My Command", desc: "What it does", shortcut: "⌘X" }.
  5. 5
    Wire pick() to real actionsReplace the alert() in pick(i) with a switch on visible[i].name or a map of command names to handler functions.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

SaaS dashboard navigation
Replace deep navigation menus like the mega menu with a command palette. Users type instead of clicking through multiple levels to find an action.
Developer tool quick actions
Add to any developer tool for keyboard-first power users — pair with a keyboard shortcuts cheatsheet. Wire commands to real actions: navigate to files, run builds, toggle settings.
Learn keyboard event handling and DOM rendering
The palette uses keydown, metaKey/ctrlKey detection, and dynamic DOM rendering. Edit the JS to understand how each part works.
Prototype keyboard-first UX
Use the palette in a prototype to test whether a keyboard-centric navigation model works for your user base before building a full implementation.
Customise grouping and icons
Update the group field on COMMANDS to create your own sections. Change the icon field to SVG strings or emoji to match your visual style.
Accessibility-first navigation
The command palette makes deep features discoverable without hunting through menus — valuable for power users and keyboard-only users alike.
Related: App Store Rating Prompt Modal
See the App Store Rating Prompt Modal for a related modals pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

A document.addEventListener("keydown") handler checks (e.metaKey || e.ctrlKey) && e.key === "k". metaKey is true on Mac for the Command key; ctrlKey is true on Windows/Linux for Control. e.preventDefault() stops the browser default Cmd+K action. Then openPalette() is called.

filter(q) converts the query to lowercase and filters COMMANDS where c.name.toLowerCase().includes(lq) or c.desc.toLowerCase().includes(lq). Both name and description are searched. The filtered array is passed to render() which rebuilds the grouped list.

The keydown handler on the input catches ArrowDown (increment activeIdx), ArrowUp (decrement), and Enter (execute). setActive(i) removes .active from all items, adds it to the item with data-idx={i}, and calls el.scrollIntoView({ block: "nearest" }) to keep the active item visible.

Replace the alert() in pick(i) with your action logic. Use a switch on visible[i].name, or create an actions map: const handlers = { "Go to Home": () => router.push("/"), ... }. Then pick calls handlers[visible[i].name]?.().

Add objects to the COMMANDS array in the JS panel: { group: "MyGroup", icon: "⭐", name: "My Action", desc: "Does something useful", shortcut: "" }. The render function groups and displays them automatically.

Yes. Click "JSX" for a React component. In React, manage open state with useState, filter state with useState, and active index with useState. Use useEffect to add/remove the document keydown listener. Wire the search input to a controlled value.