--- name: Command Palette Developer description: This skill should be used when the user asks to "create a command palette", "build a command palette", "add command palette", "implement ⌘K search", "create search modal", "build keyboard navigation", "add command menu", "create Raycast-style interface", "build spotlight search", or mentions cmdk, command bar, command menu, or keyboard-first navigation. Provides comprehensive guidance for building professional command palettes with React, TypeScript, Tailwind, and modern tooling including cmdk, Floating UI, Zustand, Tanstack Query, and Tanstack Virtual. version: 1.0.0 --- # Command Palette Development Build professional command palette interfaces for web applications using React, TypeScript, and Tailwind CSS. Command palettes provide keyboard-first navigation that enables power users to access functionality without leaving the keyboard, combining CLI efficiency with GUI discoverability. ## Purpose & When to Use Command palettes solve the tension between feature-rich applications and clean interfaces. Instead of cluttering screens with buttons and menus, palettes consolidate functionality into a searchable, keyboard-driven interface that appears on demand (typically via ⌘K or ⌘+Shift+P). Use command palettes when building applications that: - Have numerous actions or navigation targets (20+ commands) - Serve power users who prefer keyboard workflows - Need searchable, discoverable functionality - Require context-aware command suggestions - Want to provide multi-step command flows (e.g., select repository → choose action) This skill provides generator scripts, templates, examples, and comprehensive guidance for implementing command palettes matching the quality of Raycast, Linear, GitHub, and Notion. ### Choosing Implementation Patterns **Modal Palette** - Centered overlay with backdrop (⌘K standard): - Use for: App-wide actions, global search, navigation - Examples: GitHub's command palette, VS Code's command palette - Generated with: `create-command-palette.sh --type modal` **Embedded Palette** - Floating element attached to trigger: - Use for: Contextual actions, inline search, form controls - Examples: Notion's slash commands, mention autocomplete - Generated with: `create-command-palette.sh --type embedded` **Drawer Palette** - Slide-in panel from screen edge: - Use for: Filter panels, advanced search, settings navigation - Examples: Raycast's Store, application settings - Generated with: `create-command-palette.sh --type drawer` ## Quick Start Guide ### 1. Initial Setup Install dependencies and create base configuration: ```bash cd /path/to/your/project /path/to/skills/command-palette-dev/scripts/setup-palette-stack.sh ``` This script: - Detects your package manager (npm/pnpm/yarn/bun) - Installs required packages: `cmdk`, `@floating-ui/react`, `zustand`, `@tanstack/react-query`, `@tanstack/react-virtual` - Creates `ThemeProvider.tsx` and `CommandProvider.tsx` - Sets up `command-registry.ts` for command registration - Adds Tailwind configuration for palette variants - Validates existing dependencies and suggests remediation if issues found ### 2. Generate Your First Palette Create a basic modal command palette: ```bash ./scripts/create-command-palette.sh \ --type modal \ --name SearchPalette \ --output ./src/components ``` This generates: - `SearchPalette.tsx` - Main component with keyboard navigation - `SearchPalette.types.ts` - TypeScript interfaces - `index.ts` - Barrel export ### 3. Integrate into Application Wrap your app with providers: ```typescript // src/App.tsx import { ThemeProvider } from './providers/ThemeProvider'; import { CommandProvider } from './providers/CommandProvider'; import { SearchPalette } from './components/SearchPalette'; function App() { return ( ); } ``` Register commands: ```typescript // Anywhere in your app import { useCommandRegistry } from './providers/CommandProvider'; function MyComponent() { const registry = useCommandRegistry(); useEffect(() => { registry.register({ id: 'navigate-home', label: 'Go to Dashboard', keywords: ['home', 'dashboard', 'main'], shortcut: 'g then d', icon: HomeIcon, onSelect: () => navigate('/'), }); }, []); } ``` ### 4. Customize Layout and Results Generate specific layout patterns: ```bash # Two-column with preview panel (Raycast style) ./scripts/create-palette-layout.sh \ --layout two-column \ --name FileSearch \ --with-preview # Card grid for rich results (Raycast Store style) ./scripts/create-palette-layout.sh \ --layout card-grid \ --name StorePalette \ --virtualized ``` Create typed result components: ```bash # Person results with avatars ./scripts/create-result-type.sh \ --type person \ --name PersonResult # File results with icons and metadata ./scripts/create-result-type.sh \ --type file \ --name FileResult \ --with-actions ``` ## Core Concepts ### Command Palette Anatomy Every command palette consists of four essential parts: 1. **Trigger** - Keyboard shortcut or button that opens the palette (⌘K, ⌘+Shift+P) 2. **Input Field** - Search box with real-time fuzzy filtering 3. **Results List** - Filtered commands with keyboard navigation (arrow keys, enter) 4. **Footer** (optional) - Keyboard legend showing available shortcuts The cmdk library handles filtering, keyboard navigation, and accessibility automatically. Focus on command registration and result rendering. ### Layout Patterns Command palettes support multiple layout configurations depending on data richness and use case: **Single-Column List** - Basic vertical list of results: - Best for: Simple actions, text-heavy commands, mobile - Performance: Excellent (handles 2,000-3,000 items) - Reference: `references/layouts.md` for implementation details **Two-Column with Preview** - List on left, detail panel on right: - Best for: Files, documents, rich content needing preview - Examples: Raycast file search, GitHub repository picker - Requires: Preview component that updates on selection change **Multi-Panel** - Sidebar filters + center results + right details: - Best for: Complex filtering, data tables, admin panels - Examples: AWS console command palette - Consideration: Responsive behavior on smaller screens **Card Grid** - Rich cards with images, badges, metadata: - Best for: Extensions, plugins, visual content - Examples: Raycast Store, Figma plugin browser - Requires: Virtual scrolling for 100+ items **Horizontal Cards + Lists** - Mixed layout with scrollable cards and list items: - Best for: Grouped content types, contextual results - Examples: Linear's command palette - Implementation: Combine multiple result type components For detailed layout implementations and responsive strategies, see `references/layouts.md`. ### Result Types Different command types require different visual presentations: - **Person** - Avatar, name, email/role, status indicators - **File** - File type icon, name, size, modification date - **Action** - Action icon, label, description, keyboard shortcut - **Card** - Image, title, description, badges, metadata Generate result components with `create-result-type.sh` to get type-safe, accessible implementations matching your design system. ### State Management with Zustand Command palettes maintain several state concerns: ```typescript interface CommandPaletteState { isOpen: boolean; // Palette visibility searchQuery: string; // Current search text selectedId: string | null; // Active result recentCommands: Command[]; // Usage history favorites: string[]; // Pinned commands commandStack: Command[]; // Multi-step navigation breadcrumb } ``` The generated `CommandProvider` uses Zustand for lightweight, performant state management. For server-side search, Tanstack Query handles caching and loading states separately. Detailed state patterns and integration with Tanstack Query are documented in `references/state-management.md`. ### Theming System All generated palettes support three theme modes: - **Light** - Light backgrounds, dark text - **Dark** - Dark backgrounds, light text - **System** - Follows OS preference via `prefers-color-scheme` Themes use CSS variables for runtime switching without re-renders: ```css :root { --palette-bg: white; --palette-text: black; } [data-theme="dark"] { --palette-bg: #1a1a1a; --palette-text: white; } ``` Tailwind's dark mode integrates seamlessly. For custom theme creation and per-palette overrides, see `references/theming.md`. ## Generator Scripts Guide Five generator scripts create components without reading templates into context: ### create-command-palette.sh Generate complete palette components: ```bash ./scripts/create-command-palette.sh \ --type modal|embedded|drawer \ --name ComponentName \ --output ./src/components \ --theme light|dark|system ``` **Flags:** - `--type` (required) - Palette variant: modal, embedded, drawer - `--name` (required) - Component name in PascalCase - `--output` (default: ./src/components) - Output directory - `--theme` (default: system) - Theme mode - `--with-footer` (default: true) - Include keyboard legend - `--with-groups` (default: true) - Support command groups - `--interactive` - Prompt for all options ### create-palette-layout.sh Generate layout-specific components: ```bash ./scripts/create-palette-layout.sh \ --layout single-column|two-column|multi-panel|card-grid|horizontal-cards \ --name ComponentName \ --virtualized ``` **Flags:** - `--layout` (required) - Layout pattern - `--name` (required) - Component name - `--output` (default: ./src/components) - Output directory - `--virtualized` (default: false) - Enable Tanstack Virtual for 10k+ items - `--with-preview` (default: true for two-column) - Add preview panel ### create-result-type.sh Generate typed result components: ```bash ./scripts/create-result-type.sh \ --type person|file|action|card \ --name ResultComponent \ --with-actions ``` **Flags:** - `--type` (required) - Result type - `--name` (required) - Component name - `--output` (default: ./src/components/results) - Output directory - `--with-avatar` (default: true for person) - Include avatar - `--with-icon` (default: true) - Include icon - `--with-metadata` (default: true) - Include metadata line - `--with-actions` (default: false) - Include inline action buttons ### setup-palette-stack.sh Initial project setup: ```bash ./scripts/setup-palette-stack.sh \ --project-root . \ --with-examples ``` **What it does:** 1. Detects package manager 2. Validates Node/TypeScript versions 3. Installs dependencies with version compatibility check 4. Creates provider components 5. Initializes command registry 6. Configures Tailwind for palettes 7. Optionally copies working examples ### add-palette-feature.sh Add features to existing palettes: ```bash ./scripts/add-palette-feature.sh \ --feature virtual-scroll|server-search|keyboard-shortcuts|recent-commands|favorites|multi-step \ --target ./src/SearchPalette.tsx ``` **Features:** - `virtual-scroll` - Tanstack Virtual for 10k+ items - `server-search` - Tanstack Query integration with debouncing - `keyboard-shortcuts` - ⌘+1-9 favorites and custom bindings - `recent-commands` - Track and display recent usage - `favorites` - Pin commands with persistence - `multi-step` - Nested command flows with breadcrumbs ### Workflow Patterns **Basic palette creation:** ```bash setup-palette-stack.sh create-command-palette.sh --type modal --name Actions ``` **Rich file search:** ```bash create-palette-layout.sh --layout two-column --name FileSearch create-result-type.sh --type file --name FileResult add-palette-feature.sh --feature virtual-scroll --target FileSearch.tsx ``` **API-driven search:** ```bash create-command-palette.sh --type modal --name ApiSearch add-palette-feature.sh --feature server-search --target ApiSearch.tsx ``` ## Additional Resources ### Reference Files Comprehensive documentation in `references/`: - **`design-principles.md`** - UX patterns, fuzzy search, discovery, accessibility from research - **`layouts.md`** - Detailed implementation guides for all five layout patterns - **`theming.md`** - CSS variables, Tailwind integration, custom themes, reduced motion - **`keyboard-navigation.md`** - Arrow keys, shortcuts, focus traps, multi-key sequences - **`state-management.md`** - Zustand patterns, command registry, Tanstack Query integration - **`server-side-search.md`** - API integration, debouncing, pagination, infinite scroll - **`virtual-scrolling.md`** - Tanstack Virtual setup, performance benchmarks, dynamic heights - **`testing.md`** - Vitest + RTL unit tests, Playwright E2E, performance testing - **`floating-positioning.md`** - Floating UI middleware for embedded palettes - **`plugin-system.md`** - Extensibility patterns, third-party command providers - **`analytics.md`** - Telemetry patterns (reference only, not in examples) ### Example Implementations Working examples in `examples/`: - **`file-search/`** - Virtual scroll, fuzzy search, file metadata, recent files - **`action-palette/`** - Grouped actions, keyboard shortcuts, icons - **`navigation/`** - Breadcrumbs, route groups, search history - **`multi-step/`** - Nested commands, command chaining, back navigation (Raycast-style) - **`server-search/`** - API integration, Tanstack Query, debounce, loading states - **`virtual-list/`** - 10k+ items, Tanstack Virtual, performance optimizations Each example includes a README explaining what it demonstrates and key implementation details. ### Utility Functions Reusable TypeScript utilities in `utilities/`: - **`fuzzy-search.ts`** - Fuzzy matching, scoring, highlight rendering - **`keyboard-shortcuts.ts`** - Shortcut parsing, matching, hooks, display formatting - **`command-registry.ts`** - Command registration API, searching, grouping, providers - **`theme-utils.ts`** - Theme detection, switching, CSS variable generation Copy these files into your project and customize as needed. ### Scripts Directory All generator scripts with dependency validation: - **`create-command-palette.sh`** - Main palette generator - **`create-palette-layout.sh`** - Layout variants - **`create-result-type.sh`** - Result components - **`setup-palette-stack.sh`** - Initial project setup - **`add-palette-feature.sh`** - Feature additions Scripts validate dependencies before generation and provide remediation steps for missing or incompatible packages. ## Best Practices **Performance:** - Use virtual scrolling (Tanstack Virtual) for 1,000+ items - Debounce server searches (300-500ms) - Memoize result components to prevent re-renders - Lazy load preview content **Accessibility:** - Maintain focus trap when palette is open - Announce result count changes to screen readers - Support keyboard-only navigation - Respect `prefers-reduced-motion` **User Experience:** - Show recent/frequent commands on open - Provide empty state guidance for new users - Display keyboard shortcuts next to commands - Support fuzzy search for typo tolerance **Architecture:** - Keep command registration decentralized (register in feature components) - Use Zustand for UI state, Tanstack Query for server state - Separate result rendering from business logic - Design for plugin extensibility from the start For detailed guidance on each best practice, consult the relevant reference documentation. ## Getting Help **Common Issues:** 1. **Palette doesn't open** - Check keyboard shortcut conflicts, verify trigger is registered 2. **Search not filtering** - Ensure commands have `keywords` array, check fuzzy search configuration 3. **Results not rendering** - Verify result type components are imported, check TypeScript types 4. **Poor performance** - Enable virtual scrolling, check for unnecessary re-renders with React DevTools **Deep Dives:** - Layout not working as expected → `references/layouts.md` - Theme not switching → `references/theming.md` - Keyboard nav issues → `references/keyboard-navigation.md` - Server search slow → `references/server-side-search.md` - Testing failures → `references/testing.md` **Extending:** - Adding custom result types → `create-result-type.sh --type custom` - Third-party integrations → `references/plugin-system.md` - Performance optimization → `references/virtual-scrolling.md` - Analytics/telemetry → `references/analytics.md`