PixelCommand

Command palette overlay with fuzzy search, grouped items, keyboard shortcut binding, focus trap, scroll lock and Escape-to-close.

  • Configurable global shortcut (default mod+k) toggles the palette open from anywhere
  • Grouped items with headings, icons, keywords for search, and per-item keyboard hints
  • Full keyboard navigation: ArrowUp/Down, Home/End, Enter to select, Escape to close
  • Surface-aware chrome (pixel vs linear) from the nearest PxlKitSurfaceProvider
  • Combobox + listbox a11y pattern with aria-activedescendant for assistive tech
Status
stable
Category
overlays
Since
v1.8.0

API

import { PixelCommand } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
open (required)boolean—Whether the palette is visible; set it from onOpenChange.
onOpenChange (required)(open: boolean) => void—Called with the open state the palette asks for: its shortcut toggles it; Escape and the backdrop close it.
shortcutstring'mod+k'Global shortcut that toggles the palette, such as mod+k (Cmd or Ctrl + K).
placeholderstring'Type a command or search…'Placeholder of the search field.
emptyMessagestring'No results.'Shown instead of the list when nothing matches.
groups (required)PixelCommandGroup[]—The commands, by group.
surface'pixel' | 'linear'—Surface override; defaults to the nearest provider.

ref points to <div>.

Accessibility

WCAG target: 2.1 AA

  • role="dialog" with aria-modal="true" for the palette container
  • role="combobox" on the input with aria-expanded and aria-controls
  • role="listbox" on the results list with role="option" items
  • aria-activedescendant points at the highlighted option for screen readers
  • Focus trap inside the panel and scroll lock on body while open

Items without matching results render an emptyMessage region instead of the listbox; aria-expanded and aria-controls track whether the listbox is currently mounted.

Keyboard

KeyActionWhen
ArrowDownMoves highlight to the next item (wraps)—
ArrowUpMoves highlight to the previous item (wraps)—
HomeJumps highlight to the first item—
EndJumps highlight to the last item—
EnterInvokes onSelect on the highlighted item—
EscapeCloses the palettepalette is open
mod+kToggles the palette open/closed (configurable via the shortcut prop)—

Usage

import { useState } from 'react';
import { PixelCommand } from '@pxlkit/ui-kit';

export function Default() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>
        Open command palette
      </button>
      <PixelCommand
        open={open}
        onOpenChange={setOpen}
        groups={[
          {
            heading: 'Actions',
            items: [
              {
                id: 'new-file',
                label: 'New file',
                shortcut: 'Ctrl+N',
                onSelect: () => setOpen(false),
              },
              {
                id: 'open-file',
                label: 'Open file…',
                shortcut: 'Ctrl+O',
                onSelect: () => setOpen(false),
              },
              {
                id: 'save',
                label: 'Save',
                shortcut: 'Ctrl+S',
                onSelect: () => setOpen(false),
              },
            ],
          },
          {
            heading: 'Navigation',
            items: [
              {
                id: 'go-home',
                label: 'Go to home',
                keywords: ['dashboard', 'start'],
                onSelect: () => setOpen(false),
              },
              {
                id: 'go-settings',
                label: 'Go to settings',
                keywords: ['preferences', 'config'],
                onSelect: () => setOpen(false),
              },
            ],
          },
        ]}
      />
    </>
  );
}

Examples

Default

import { useState } from 'react';
import { PixelCommand } from '@pxlkit/ui-kit';

export function Default() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>
        Open command palette
      </button>
      <PixelCommand
        open={open}
        onOpenChange={setOpen}
        groups={[
          {
            heading: 'Actions',
            items: [
              {
                id: 'new-file',
                label: 'New file',
                shortcut: 'Ctrl+N',
                onSelect: () => setOpen(false),
              },
              {
                id: 'open-file',
                label: 'Open file…',
                shortcut: 'Ctrl+O',
                onSelect: () => setOpen(false),
              },
              {
                id: 'save',
                label: 'Save',
                shortcut: 'Ctrl+S',
                onSelect: () => setOpen(false),
              },
            ],
          },
          {
            heading: 'Navigation',
            items: [
              {
                id: 'go-home',
                label: 'Go to home',
                keywords: ['dashboard', 'start'],
                onSelect: () => setOpen(false),
              },
              {
                id: 'go-settings',
                label: 'Go to settings',
                keywords: ['preferences', 'config'],
                onSelect: () => setOpen(false),
              },
            ],
          },
        ]}
      />
    </>
  );
}

Custom shortcut

import { useState } from 'react';
import { PixelCommand } from '@pxlkit/ui-kit';

export function WithCustomShortcut() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>
        Open (or press Ctrl+Shift+P)
      </button>
      <PixelCommand
        open={open}
        onOpenChange={setOpen}
        shortcut="mod+shift+p"
        placeholder="Run a command…"
        groups={[
          {
            heading: 'Commands',
            items: [
              {
                id: 'reload',
                label: 'Reload window',
                onSelect: () => setOpen(false),
              },
              {
                id: 'toggle-theme',
                label: 'Toggle theme',
                onSelect: () => setOpen(false),
              },
            ],
          },
        ]}
      />
    </>
  );
}

Linear surface

import { useState } from 'react';
import { PixelCommand } from '@pxlkit/ui-kit';

export function LinearSurface() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>
        Open linear palette
      </button>
      <PixelCommand
        open={open}
        onOpenChange={setOpen}
        surface="linear"
        emptyMessage="Nothing matches your search."
        groups={[
          {
            heading: 'Recent',
            items: [
              {
                id: 'doc-1',
                label: 'Project roadmap',
                onSelect: () => setOpen(false),
              },
              {
                id: 'doc-2',
                label: 'Sprint notes',
                onSelect: () => setOpen(false),
              },
            ],
          },
        ]}
      />
    </>
  );
}

Related