
Implementing Command Palettes
Use when building Cmd+K command palettes in React - covers keyboard navigation with...
Install
npx skills add AgentWorkforce/relay --skill implementing-command-palettes -g -a claude-code -y- Repository
- AgentWorkforce/relay1.1k
- Category
- Engineering
- Updated
- 3d ago
- License
- Apache-2.0
- Context cost
- Mediumabout 2,386 tokens
- Runs scripts
- No, instructions only
What it does
Use when building Cmd+K command palettes in React - covers keyboard navigation with arrow keys, keeping selected items in view with scrollIntoView, filtering with shortcut matching, and preventing infinite re-renders from reference instability
Implementing Command Palettes
Overview
Command palettes (Cmd+K / Ctrl+K) need precise keyboard navigation, scroll behavior, and stable references to avoid re-render loops. This skill covers the mechanical patterns that make command palettes feel responsive.
When to Use
- Building a Cmd+K command palette in React
- Implementing arrow key navigation with visual selection
- Keeping selected items visible during keyboard navigation
- Filtering commands by label text AND keyboard shortcuts
- Experiencing infinite re-renders when commands update
Quick Reference
| Feature | Implementation |
|---|---|
| Arrow navigation | Track selectedIndex, clamp with Math.min/max |
| Keep in view | scrollIntoView({ block: 'nearest', behavior: 'smooth' }) |
| Shortcut matching | Strip spaces from shortcuts, match against query |
| Stable icons | Define icon elements outside component |
| Stable handlers | useCallback + noop constant for disabled states |
Keyboard Navigation
Index Management
const [selectedIndex, setSelectedIndex] = useState(0);
useEffect(() => {
if (!isOpen) return;
const handleKeyDown = (e: KeyboardEvent) => {
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
// Clamp to last item
setSelectedIndex((prev) => Math.min(prev + 1, filteredItems.length - 1));
break;
case 'ArrowUp':
e.preventDefault();
// Clamp to first item
setSelectedIndex((prev) => Math.max(prev - 1, 0));
break;
case 'Enter':
e.preventDefault();
if (filteredItems[selectedIndex]) {
executeCommand(filteredItems[selectedIndex]);
close();
}
break;
case 'Escape':
e.preventDefault();
close();
break;
}
};
