Skip to content

CommandPalette

You provide a search function, sync or async, that returns groups; the palette handles focus, arrow keys, highlighting and live announcements. Bind it to Mod+K with useCommandPaletteShortcut.

import { useState } from 'react'; import { Button, CommandPalette, KeyHint, toast, useCommandPaletteShortcut, } from '@andrewbehma/glass-ui'; import { FolderKanban, Inbox, Plus, Search, Settings, UserPlus, } from 'lucide-react';

Playground

CommandPalette.tsx
import { useState } from 'react';
import {
Button,
CommandPalette,
KeyHint,
toast,
useCommandPaletteShortcut,
} from '@andrewbehma/glass-ui';
import {
FolderKanban,
Inbox,
Plus,
Search,
Settings,
UserPlus,
} from 'lucide-react';
function Example() {
const [open, setOpen] = useState(false);
useCommandPaletteShortcut(() => setOpen(true));
const groups = [
{
id: 'go',
title: 'Go to',
items: [
{ id: 'inbox', label: 'Inbox', icon: Inbox, hint: 'G I' },
{ id: 'projects', label: 'Projects', icon: FolderKanban, hint: 'G P' },
{ id: 'settings', label: 'Settings', icon: Settings },
],
},
{
id: 'create',
title: 'Create',
items: [
{ id: 'issue', label: 'New issue', icon: Plus, keywords: ['bug', 'task'] },
{ id: 'invite', label: 'Invite teammate', icon: UserPlus },
],
},
];
const search = (query) =>
groups
.map((g) => ({
...g,
items: g.items.filter((i) =>
[i.label, ...(i.keywords ?? [])].join(' ').toLowerCase().includes(query.toLowerCase()),
),
}))
.filter((g) => g.items.length > 0);
return (
<>
<Button onClick={() => setOpen(true)}>
Open palette <KeyHint keys="Mod+K" />
</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
search={search}
placeholder="Search commands"
onSelect={(item) => toast(item.label)}
/>
</>
);
}