Skip to content

Components

A React Command Palette With Zero Dependencies — ⌘K Without the Kitchen Sink

Fuzzy Search, Keyboard Nav and Focus Trapping in One File You Actually Own
Written by Aiden Wood Founder and Lead Design Engineer
⌘ 🔍 ⚡

Every app eventually grows a ⌘K palette, and every team reaches for the same two options: cmdk (plus Radix, plus a styling layer) or kbar (plus its store, plus its portal stack). You wanted a search box with arrow keys. You got a dependency tree.

Velocity X's standard-command-palette takes the other road: one React file, installed into your codebase by CLI. No package to pin, no breaking minor version six months from now, no fighting someone else's theme tokens.

The Setup

velocityx add standard-command-palette

That drops the full source at components/velocity/standard-command-palette/. It's yours now — ownership of the file, styled with your Tailwind config, readable top to bottom in one sitting. (The velocityx CLI is in preview and not on npm yet — the free tier's source is public on GitHub in the meantime.)

The Money Pattern

The part most hand-rolled palettes get wrong is the keyboard model. This one handles it in ~40 lines: a single keydown handler owns open/close, arrow traversal, and Enter-to-commit, with focus trapped inside the dialog while it's open.

useEffect(() => {
  const onKey = (e: KeyboardEvent) => {
    if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
      e.preventDefault();
      setOpen(o => !o);
    }
    if (e.key === 'Escape') setOpen(false);
  };
  window.addEventListener('keydown', onKey);
  return () => window.removeEventListener('keydown', onKey);
}, []);

Filtering is a scored subsequence match — "nvs" finds "New Visit Summary" — not a 12KB fuzzy-search dependency. Spoiler: for a list of commands measured in dozens, a 15-line scorer and a 12KB library return the same results.

The Catch

Owning the source means owning the source. If you want new behaviour, you edit a file instead of bumping a version — which is the point, but it's a different muscle. Velocity X softens this with versioned upgrades: velocityx upgrade diffs against your lockfile and refuses to stomp local edits.

And it assumes an app shell — focus management and keyboard conventions are baked in. If you need a bare combobox primitive, this is the wrong tool; grab a Core UI input instead.

The Verdict

A command palette is ~300 lines of genuinely tricky UI. Renting those lines from a dependency tree is how node_modules got its reputation. Installing them as readable source you can restyle, extend and pin — that's the trade Velocity X is making across its 400+ component library, and the palette is the best place to feel the difference.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.