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
| Prop | Type | Default | Description |
|---|---|---|---|
| commands required | CommandBarCommand[] | — | Commands shown, filtered, and grouped by `category`. |
| config required | CommandBarConfig | — | `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
| Prop | Type | Default | Description |
|---|---|---|---|
| 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
| Prop | Type | Default | Description |
|---|---|---|---|
| id required | string | — | Unique identifier. |
| label required | string | — | 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
| Prop | Type | Default | Description |
|---|---|---|---|
| id required | string | — | Stable key for the subgroup row. |
| label required | string | — | 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
| Prop | Type | Default | Description |
|---|---|---|---|
| query required | string | — | Current search string (same as the palette input). |
| subgroupId required | string | — | 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
CommandBarregistersconfigon the shared state — avoid mounting multiple instances with different configs at once. - Pass
recentCommandIdsplusconfig.onTrackRecentto 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.