AI
NUI logov3.1.0

Command Palette

An accessible modal command search dialog following the WAI-ARIA combobox pattern. Triggered via global keyboard shortcuts (⌘K or Ctrl+K), it provides instant fuzzy search, categorized action groups, and keyboard navigation.

tsx
import { CommandPalette } from '@nofinite/nui';

Interactive Preview


Key Features

  • Global Hotkey Support: Automatically listens for ⌘K / Ctrl+K and Escape triggers.
  • Categorized Sections: Group commands logically into Navigation, Quick Actions, Settings, or Recent Files.
  • Fuzzy Filtering: Fast client-side search ranking that handles typos and partial string matches.
  • Accessible Focus Management: Traps focus inside the dialog and maintains visual focus indicators across list items using ARIA activedescendant.

Usage

Basic Usage

tsx
import { useState, useEffect } from 'react';
import { CommandPalette, Button, Kbd } from '@nofinite/nui';

export default function AppCommandSearch() {
  const [isOpen, setIsOpen] = useState(false);

  // Optional: Global keydown listener
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        setIsOpen((prev) => !prev);
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, []);

  const sections = [
    {
      title: 'Navigation',
      items: [
        { id: '1', label: 'Go to Documentation', shortcut: '⌘D', onSelect: () => window.location.href = '/docs' },
        { id: '2', label: 'Explore Components', shortcut: '⌘C', onSelect: () => window.location.href = '/nui/components/button' },
      ]
    },
    {
      title: 'Actions',
      items: [
        { id: '3', label: 'Create New Document', shortcut: '⌘N', onSelect: () => alert('Document Created!') },
        { id: '4', label: 'Toggle Dark Mode', shortcut: '⌘T', onSelect: () => alert('Theme Toggled!') }
      ]
    }
  ];

  return (
    <>
      <Button variant="outline" onClick={() => setIsOpen(true)}>
        Search commands... <Kbd className="ml-2">⌘K</Kbd>
      </Button>

      <CommandPalette
        open={isOpen}
        onOpenChange={setIsOpen}
        sections={sections}
        placeholder="Type a command or search..."
      />
    </>
  );
}

Keyboard Interaction

KeyBehavior
⌘K / Ctrl+KOpen or close the command palette dialog
ArrowDownFocus the next command item
ArrowUpFocus the previous command item
EnterTrigger the currently highlighted command
EscapeClose the command palette and restore trigger focus

Best Practices

Do

  • Provide concise, action-oriented titles for commands (e.g., "Toggle Fullscreen" rather than "Fullscreen").
  • Display relevant keyboard shortcuts in command descriptions to educate users over time.
  • Restore focus back to the user's previous active element when the palette closes.

Don't

  • Do not clutter the palette with hundreds of low-frequency or trivial links; prioritize primary workflows.
  • Avoid slow network requests on every keystroke; prefer fast in-memory filtering.

API Reference

PropTypeDefaultDescription
sections*CommandSection[]——
placeholderstringSearch commands…—
classNamestring——
openboolean—Forces the palette open/closed. If undefined, it operates purely via Cmd+K internally.
onOpenChange((open: boolean) => void)——