Skip to content

CommandPalette

Search and jump: pages, servers, skills and actions from one ⌘K / Ctrl+K box.

OverlaysIsland

Examples

With its own trigger

The live, page-wide palette is the "Search docs" box in the topbar: press ⌘K / Ctrl+K anywhere. This second palette passes shortcut={false} so only its button opens it. Choosing an item here only changes the URL hash.

Example
<CommandPalette
  id="servers-palette"
  trigger
  shortcut={false}
  triggerLabel="Jump to a server or skill"
  placeholder="Search servers, skills, actions…"
  items={[
    { group: 'Servers', label: 'GitHub', href: '/servers/github', icon: 'github', hint: 'mcp.github.com' },
    { group: 'Servers', label: 'Linear', href: '/servers/linear', icon: 'server', hint: 'mcp.linear.app' },
    { group: 'Servers', label: 'Sentry', href: '/servers/sentry', icon: 'server', keywords: ['errors'] },
    { group: 'Skills', label: 'Triage new issues', href: '/skills/triage', icon: 'book-open' },
    { group: 'Actions', label: 'Add server', href: '/servers?dialog=add-server', icon: 'plus' },
    { group: 'Actions', label: 'Rotate token', href: '/settings/tokens', icon: 'key' },
  ]}
/>

Usage

Usage
import { CommandPalette } from '@switchboard/ui'

// Once, in the app topbar.
<CommandPalette items={commandItems} trigger />

Props

Every component also takes mix, for css() and mixins applied after its own style.

CommandPalette

CommandPalette props
PropTypeDefaultDescription
items*CommandItem[]–Grouped in the order their group first appears.
idstring'command-palette'id of the <dialog>. Give a second palette on the page its own.
triggerboolean–Render the search-style trigger button. Without it only the shortcut opens the palette.
triggerLabelstring'Search or jump to…'Trigger text.
placeholderstring'Search pages, servers, skills…'Search input placeholder.
shortcutbooleantrueToggle on ⌘K / Ctrl+K. Only one palette per page should listen.
defaultOpenboolean–Start open (tests, demos).

CommandItem

CommandItem props
PropTypeDefaultDescription
group*string–Group heading: "Servers", "Skills", "Actions".
label*string–Item text; the first query word is bolded in it.
href*string–Where choosing goes. Also the item key, so unique.
iconIconName'chevron-right'Leading icon.
keywordsstring[]–Extra search terms: aliases, ids.
hintstring–Right-aligned mono hint, e.g. a host.

Choosing dispatches a cancelable sb:command event ({ href }) on the dialog, then navigates unless prevented.

Accessibility

  • A modal <dialog> named "Command palette": page inert, Escape closes, focus returns to what had it.
  • The input is a combobox with aria-activedescendant over a grouped listbox; focus stays in the input while arrows move the highlight.
  • Arrow keys move, Ctrl+Home/End jump, Enter opens. "No matches" is announced through role="status".
  • The trigger advertises the shortcut with aria-keyshortcuts (omitted when shortcut is false).

Guidance

Do

  • Mount one listening palette per page, in the topbar.
  • Add keywords for names people search by: ids, old names, hosts.

Don’t

  • Mount two palettes that both listen for ⌘K / Ctrl+K.
  • Put destructive actions in the palette; link to the page that has them.