Skip to content

CommandPalette

Purpose

CommandPalette is the shared UI for listing and selecting commands.

  • Built on cmdk + shadcn-style command primitives
  • Expects command data (including grouping) from useCommandPalette
  • Keeps the “what commands exist” logic out of the UI layer

When to use

Use CommandPalette when:

  • You want a consistent “Cmd/Ctrl+K” experience across routes
  • You want global search + action execution in one surface
  • Commands are defined in feature modules but rendered centrally

Example

tsx
import React, { useMemo } from 'react'
import { useCommandPalette, type Command } from '@/shared/hooks'
import { CommandPalette } from '@/shared/ui/components/CommandPalette'

export function AppCommandPalette() {
  const initialCommands: Command[] = useMemo(
    () => [
      {
        id: 'go-dashboard',
        label: 'Go to Dashboard',
        group: 'Navigation',
        shortcut: 'G D',
        action: async () => {
          // navigate('/dashboard')
        },
      },
      {
        id: 'refresh-data',
        label: 'Refresh data',
        group: 'Actions',
        action: async () => {
          // queryClient.invalidateQueries(...)
        },
      },
    ],
    []
  )

  const palette = useCommandPalette({ initialCommands })

  return (
    <CommandPalette
      open={palette.isOpen}
      onOpenChange={(open) => (open ? palette.open() : palette.close())}
      commands={palette.commands}
      groupedCommands={palette.groupedCommands}
      onSelect={(cmd) => palette.execute(cmd.id)}
    />
  )
}

Props (concise)

  • open / onOpenChange(open)
  • commands: Command[]
    • The full flat list of commands.
  • groupedCommands: Map<string, Command[]>
    • Grouped representation used for rendering sections.
  • onSelect(command)
    • Called when a user selects a command (the component won’t call it for disabled commands).
  • placeholder? / emptyText?
    • UI strings for search input and empty state.

Notes / Gotchas

  • Grouping: the component renders from groupedCommands; keep it derived from the same commands list to avoid drift.
  • Disabled commands: pass disabled: true on a command to keep it visible but non-selectable.
  • Closing behavior: useCommandPalette execute(id) closes the palette after running the action.
  • Shortcut binding: useCommandPalette registers Ctrl+K by default (implemented as ctrl: true in the hook).