cmdk: Build a fast React command menu (⌘K) — Install, Example & Best Practices
A concise, practical guide to cmdk for React developers: setup, searchable menu patterns, keyboard navigation, accessibility and advanced usage with code examples and micro-markup suggestions.
Introduction — why use cmdk for React command palettes
Command palettes (often opened with ⌘/Ctrl+K) are a powerful UI pattern: they let users find actions, navigate, and perform tasks without moving the mouse. The cmdk library provides a lightweight, composable foundation to build such searchable menus in React with predictable keyboard navigation and a small API surface.
Unlike heavy UI kits, cmdk focuses on semantics and keyboard-first interactions. That makes it ideal for apps that need responsive, accessible command menus, whether you’re adding a simple global search or a complex command center with nested groups and async results.
Throughout this guide you’ll find a working setup, an end-to-end example of a React command menu component, keyboard/accessibility considerations, and advanced patterns such as virtualization, async data and custom item rendering.
What is cmdk and when to choose it
cmdk is a React-focused toolkit for building command palettes and searchable menus. It provides primitives for focus management, keyboard navigation, and rendering items while leaving styling and state management to you. If you need a small, predictable API that plays well with custom UI and accessibility needs, cmdk is a good fit.
Pick cmdk when you care about keyboard-first UX, want a minimal dependency surface, and prefer to compose your own styles and data-fetching. If you need an out-of-the-box, opinionated UI with theming baked in, a different library may be more suitable.
The patterns you’ll implement with cmdk—filtering, grouping, keyboard navigation, and asynchronous results—translate well to many use cases: global command menus, quick-switchers, context-aware action lists, or an in-app palette for large web apps.
Installation & getting started
Install cmdk from npm or yarn. This is the fastest way to get the primitives and types into your React project.
// npm
npm install cmdk
// yarn
yarn add cmdk
If you prefer a guided walkthrough, see a practical cmdk tutorial that covers a full build from scratch. For package reference and releases, the npm package is helpful: cmdk installation.
After installing, import the core primitives (names may vary slightly depending on versions). Typical imports look like:
import { Command, CommandInput, CommandList, CommandItem } from 'cmdk';
Building a basic React command menu (example)
The simplest command palette consists of an input, a list, and a set of items. Below is a compact example demonstrating how to wire cmdk into a React component with a global toggle for ⌘/Ctrl+K.
import React, { useState, useEffect } from 'react';
import { Command, CommandInput, CommandList, CommandItem } from 'cmdk';
export default function CommandPalette({ items }) {
const [open, setOpen] = useState(false);
useEffect(() => {
function onKey(e) {
const isMac = navigator.platform.toLowerCase().includes('mac');
if ((isMac && e.metaKey && e.key === 'k') || (!isMac && e.ctrlKey && e.key === 'k')) {
e.preventDefault();
setOpen(o => !o);
}
}
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, []);
return (
open && (
<Command onClose={() => setOpen(false)} modal={true}>
<CommandInput placeholder="Search actions, pages, or files..." />
<CommandList>
{items.map(item => (
<CommandItem key={item.id} onSelect={() => item.onSelect()}>
{item.label}
</CommandItem>
))}
</CommandList>
</Command>
)
);
}
This example demonstrates core concerns: a keyboard shortcut to open the palette, a controlled open state, and a simple mapping of items. Extend it with routing, role-based actions, or search indexing to suit your app.
For searchable behavior, pre-filter your items client-side or implement async filtering in the input change handler. Debounce when calling remote endpoints to avoid excessive requests and to keep UI snappy.
Keyboard navigation and accessibility
A command menu must feel instantaneous and predictable when navigated by keyboard. cmdk primitives already provide arrow-key navigation, home/end support, and typeahead behavior, but you should audit focus trapping, ARIA attributes, and screen reader labels in your implementation.
Focus management: ensure the input receives focus when the palette opens. If you use a modal wrapper, trap focus within the palette so keyboard users don’t accidentally tab out. Use aria-label or a visually-hidden heading to describe the palette’s purpose.
Assistive labels and roles are crucial. cmdk components often map to listbox semantics; verify that items convey role=”option” (or the equivalent) and selected/focused states for screen readers.
- ⌘/Ctrl + K — open/close palette
- Esc — close palette
- Arrow Up / Arrow Down — navigate items
- Enter — execute selected item
Advanced usage: grouping, async results, and custom rendering
Real-world command menus often present grouped results (navigation, actions, recently used), custom item visuals (icons, shortcuts), and async searches (server-side suggestions). With cmdk you compose these behaviors without heavy overrides.
Grouping: build grouped sections by rendering headings inside the list and partitioning items by type. For keyboard-only users, ensure groups are announced clearly, either via insertion of offscreen labels or ARIA grouping roles.
Async data: debounce input changes and show a loading state in the list while fetching results. When results arrive, update the list items; maintain a stable key for the list container so focus is preserved where appropriate.
Custom item rendering lets you show icons, badges, and nested routes. Keep interactive elements inside items non-focusable (use aria-hidden or tabIndex=-1) to avoid breaking item-level keyboard selection.
Performance, testing and best practices
Keep the command menu performant by limiting the number of rendered items. Use virtualization (e.g., react-window) if you must render hundreds of results. For most use cases, client-side filtering over an indexed array is enough.
Test keyboard paths: write integration tests that simulate opening the palette, typing a query, navigating with arrows, and selecting an item. Automated tests help prevent regressions in focus management and accessibility; pair them with manual screen reader checks.
Design tip: surface the most likely or most-used actions first (recency and frequency). Offer a “recently used” section and allow easy pinning of actions. This reduces query depth and improves discoverability.
Micro-markup suggestion (FAQ + Article schema) for SEO
To help search engines and voice assistants, add JSON-LD for FAQs and the article. Below is a minimal FAQ schema and an article outline you can add to the page head or inline as a script tag.
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{"@type":"Question","name":"How do I install cmdk in React?","acceptedAnswer":{"@type":"Answer","text":"npm install cmdk or yarn add cmdk, then import the primitives into your React component."}},
{"@type":"Question","name":"How to open a cmdk command menu with ⌘K?","acceptedAnswer":{"@type":"Answer","text":"Listen for meta/ctrl + k in a keydown handler, prevent default, and toggle the palette open state."}},
{"@type":"Question","name":"Is cmdk accessible?","acceptedAnswer":{"@type":"Answer","text":"cmdk focuses on keyboard navigation and semantics; you should still verify ARIA roles, focus trapping and screen reader labels when integrating."}}
]
}
Tip: Use concise first-sentence answers for featured snippets and voice search; keep them short and direct (one line), and follow with supporting detail.
Links and resources
Further reading and reference links:
cmdk installation — official npm package page for releases and installation commands.
cmdk tutorial — a step-by-step tutorial implementing a React command menu (useful implementation reference).
React keyboard navigation — official React accessibility docs for general guidance on keyboard and ARIA best practices.
FAQ
How do I install cmdk in a React project?
Install with npm or yarn: npm install cmdk or yarn add cmdk. Then import the primitives (Command, CommandInput, CommandList, CommandItem) and wire them into a component. See the example above for a minimal setup.
How can I make a ⌘K keyboard toggle that works on macOS and Windows?
Listen for keydown on window and check modifier keys: use e.metaKey && e.key === 'k' for macOS and e.ctrlKey && e.key === 'k' for Windows/Linux. Prevent default and toggle the palette’s open state. Remember to cleanup the event listener on unmount.
Is cmdk accessible for screen reader users?
cmdk provides keyboard behaviors out of the box, but you must ensure proper ARIA labels, focus trapping, and informative item roles. Use aria-labels for the input and confirm that focused items announce meaningful text. Pair automated testing with manual screen reader checks.
Semantic core (grouped keywords)
Primary
cmdk, cmdk React, React command palette, React command menu, React ⌘K menu
Secondary
cmdk installation, cmdk setup, cmdk getting started, cmdk tutorial, cmdk example, React command menu component
Clarifying / Long-tail & LSI
cmdk command menu, React searchable menu, React keyboard navigation, React command palette library, cmdk advanced usage, React command palette example, searchable command menu React, cmdk setup tutorial


Recent Comments