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 requiredstring-Unique identifier.
label requiredstring-Display label.
description string-Optional description shown below the label.
icon string-Iconify icon string.
category string-Category for grouping.
shortcut string-Keyboard shortcut hint.

CommandBarSubgroup

PropTypeDefaultDescription
id requiredstring-Stable key for the subgroup row.
label requiredstring-Root list label.
description string-Optional muted line in the root list.
icon string-Iconify icon string.
category string-Category 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 requiredstring-Current search string (same as the palette input).
subgroupId requiredstring-Opened subgroup id.
back required() => void-Return to the root list without closing.
close required() => void-Close 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.