Phoundry UI

Command Bar

Searchable command palette with categories, icons, shortcuts, recent commands, and optional subgroups (nested lists or custom snippet panels).

import { CommandBar, getCommandBarState } from 'phoundry-ui';

Basic Usage

Show code
const barState = getCommandBarState();

const commands: CommandBarCommand[] = [
  { id: 'new', label: 'New File', icon: PhiIcons.document, category: 'File', shortcut: '⌘N' },
  { id: 'search', label: 'Search', icon: PhiIcons.search, category: 'Edit', shortcut: '⌘⇧F' },
];

const config = {
  onExecute: (cmd) => run(cmd),
  onTrackRecent: async (id) => persistRecent(id),
};

// Root layout:
<CommandBar {commands} {config} recentCommandIds={recentIds} />

// Anywhere:
barState.open();

Recent commands

Open the palette and run a command — executed ids bubble to the Recent group via onTrackRecent.

recent: save, search
Show code
const barConfig = {
  onExecute: (cmd) => run(cmd),
  onTrackRecent: async (id) => saveRecent(id),
};

<CommandBar commands={commands} config={barConfig} recentCommandIds={recentIds} />

Subgroups

Subgroups appear in the root list with a chevron. Choose one to drill in; Esc or the back control returns to the root. Use a content snippet for a fully custom panel instead of command rows.

Show code
const itemSubgroups: CommandBarSubgroup[] = [
  {
    id: 'file-more',
    label: 'More file actions',
    icon: PhiIcons.folder,
    category: 'File',
    items: [
      { id: 'revert', label: 'Revert file', icon: PhiIcons.refresh, category: 'File' },
    ],
  },
];

{#snippet toolsPanel(ctx)}
  <div class="p-2 text-xs">
    <p>Query: {ctx.query}</p>
    <button type="button" onclick={() => ctx.back()}>Back</button>
  </div>
{/snippet}

<CommandBar
  {commands}
  {config}
  subgroups={[
    ...itemSubgroups,
    { id: 'tools', label: 'Custom panel', category: 'App', content: toolsPanel },
  ]}
/>

CommandBar Props

PropTypeDefaultDescription
commands requiredCommandBarCommand[]Commands shown, filtered, and grouped by `category`.
config requiredCommandBarConfig`onExecute` runs after a command is chosen; optional `onTrackRecent` persists usage for `recentCommandIds`.
subgroups CommandBarSubgroup[][]Subgroup rows in the root list; each opens a nested list (`items`) or a custom snippet (`content`).
recentCommandIds string[][]Ordered ids surfaced under the **Recent** heading when the query is empty (commands only).
placeholder string'Search commands...'Placeholder on the filter input.

CommandBarConfig

PropTypeDefaultDescription
onExecute required(command: CommandBarCommand) => void | Promise<void>Runs after the user confirms a command.
onTrackRecent (commandId: string) => void | Promise<void>Optional hook to persist recency — wire into storage, then feed ids back via `recentCommandIds`.

CommandBarCommand

PropTypeDefaultDescription
id requiredstringUnique identifier.
label requiredstringDisplay label.
description stringOptional description shown below the label.
icon stringIconify icon string.
category stringCategory for grouping.
shortcut stringKeyboard shortcut hint.

CommandBarSubgroup

PropTypeDefaultDescription
id requiredstringStable key for the subgroup row.
label requiredstringRoot list label.
description stringOptional muted line in the root list.
icon stringIconify icon string.
category stringCategory for grouping in the root list.
items CommandBarCommand[]Commands shown inside the subgroup (exclusive with `content`).
content Snippet<[CommandBarSubgroupContentContext]>Custom panel inside the subgroup (exclusive with `items`); use `{@render content(ctx)}` pattern from a snippet prop.

CommandBarSubgroupContentContext

PropTypeDefaultDescription
query requiredstringCurrent search string (same as the palette input).
subgroupId requiredstringOpened subgroup id.
back required() => voidReturn to the root list without closing.
close required() => voidClose the command bar.

Usage tips

  • Call getCommandBarState() to get the singleton — it works from any component.
  • The mounted CommandBar registers config on the shared state — avoid mounting multiple instances with different configs at once.
  • Pass recentCommandIds plus config.onTrackRecent to populate the Recent section (top-level commands only).
  • Root list: ↑↓ navigate, ↵ runs a command or opens a subgroup.
  • Inside a subgroup with commands: same navigation; ↵ executes the selected command.
  • Custom subgroup: arrow navigation is disabled; esc or the back button returns to the root list.
  • Esc from the root list closes the palette; from a subgroup it goes back first.