Command Palette
Global search and jump on Cmd or Ctrl K: grouped results, prefix filters and keyboard navigation.
Picked: nothing yet
const groups = [
{
id: "sprouts",
label: "Sprouts",
items: [
{ id: "robin", label: "robin", hint: "eu-west · production", icon: <RocketIcon /> },
{ id: "wren", label: "wren", hint: "us-east · production", icon: <RocketIcon /> },
{ id: "finch", label: "finch", hint: "eu-west · staging", icon: <RocketIcon /> },
],
},
];
function Search() {
const [open, setOpen] = useState(false);
useCommandPaletteShortcut(() => setOpen((o) => !o));
return (
<>
<Button onClick={() => setOpen(true)} aria-keyshortcuts="Meta+K Control+K">
<SearchIcon />
Search
<Kbd aria-hidden="true">{shortcutLabel()}</Kbd>
</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
groups={groups}
onSelect={(item) => navigate(item.id)}
/>
</>
);
}Installation
npx shadcn@latest add https://sproutboat.com/ikada/r/command-palette.jsonThe CLI writes components/ikada/command-palette.tsx and merges the ikada theme into your CSS. It also installs the components it is built from: Kbd and Spinner. Or take it from the package: import { CommandPalette } from "@sproutboat/ikada";
Usage
import { CommandPalette } from "@/components/ikada/command-palette";
const groups = [
{
id: "sprouts",
label: "Sprouts",
items: [
{ id: "robin", label: "robin", hint: "eu-west · production", icon: <RocketIcon /> },
{ id: "wren", label: "wren", hint: "us-east · production", icon: <RocketIcon /> },
{ id: "finch", label: "finch", hint: "eu-west · staging", icon: <RocketIcon /> },
],
},
];
function Search() {
const [open, setOpen] = useState(false);
useCommandPaletteShortcut(() => setOpen((o) => !o));
return (
<>
<Button onClick={() => setOpen(true)} aria-keyshortcuts="Meta+K Control+K">
<SearchIcon />
Search
<Kbd aria-hidden="true">{shortcutLabel()}</Kbd>
</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
groups={groups}
onSelect={(item) => navigate(item.id)}
/>
</>
);
}Examples
Picked: nothing yet
const groups = [
{
id: "sprouts",
label: "Sprouts",
items: [
{ id: "robin", label: "robin", hint: "eu-west · production", icon: <RocketIcon /> },
{ id: "wren", label: "wren", hint: "us-east · production", icon: <RocketIcon /> },
{ id: "finch", label: "finch", hint: "eu-west · staging", icon: <RocketIcon /> },
],
},
];
function Search() {
const [open, setOpen] = useState(false);
useCommandPaletteShortcut(() => setOpen((o) => !o));
return (
<>
<Button onClick={() => setOpen(true)} aria-keyshortcuts="Meta+K Control+K">
<SearchIcon />
Search
<Kbd aria-hidden="true">{shortcutLabel()}</Kbd>
</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
groups={groups}
onSelect={(item) => navigate(item.id)}
/>
</>
);
}Picked: nothing yet
const groups = [
{
id: "sprouts",
label: "Sprouts",
items: [
{ id: "robin", label: "robin", hint: "eu-west · production", icon: <RocketIcon /> },
{ id: "wren", label: "wren", hint: "us-east · production", icon: <RocketIcon /> },
],
},
{
id: "databases",
label: "Databases",
items: [
{ id: "heron-db", label: "heron-db", hint: "eu-west", icon: <DatabaseIcon />, scope: "d1" },
{ id: "wren-db", label: "wren-db", hint: "us-east", icon: <DatabaseIcon />, scope: "d1" },
],
},
];
const recents = [{ id: "robin-recent", label: "robin", hint: "eu-west · production", icon: <RocketIcon /> }];
const prefixes = [{ scope: "d1", label: "D1 databases" }];
<CommandPalette
open={open}
onOpenChange={setOpen}
groups={groups}
recents={recents}
prefixes={prefixes}
onSelect={(item) => navigate(item.id)}
/>Props
| Prop | Type | Description |
|---|---|---|
| openrequired | boolean | Whether it is open (controlled). |
| onOpenChangerequired | (open: boolean) => void | Called with the new open state when it opens or closes. |
| groupsrequired | readonly PaletteGroup[] | Results to show, in order: each group a heading and its items. |
| recents | readonly PaletteItem[] | Shown first while the query is empty. Default `[]`. |
| prefixes | readonly PalettePrefix[] | Scopes typed as `scope:` that narrow the search, shown as a chip. Default `[]`. |
| onSelectrequired | (item: PaletteItem) => void | Called with the chosen item; the palette closes after it. |
| loading | boolean | Shows a spinner while results are fetched. Default `false`. |
| placeholder | string | Placeholder of the search input. Default `Search projects, versions, storage…`. |
| label | string | Name for screen readers. Default `Command palette`. |