CommandPalette
A modal, fuzzy-ranked command launcher with virtual focus, grouped results, recent commands, and Hotkey hints.
Default
The palette owns search and virtual focus; the application owns its open state and global shortcut.
<CommandPalette open={open} onClose={() => setOpen(false)} items={commands} />Installation
import { CommandPalette, rankCommandItem } from "madagent";Recent Commands
When the query is empty, recentIds pins commands in a Recent section without duplicating them.
<CommandPalette open={open} onClose={close} items={commands} recentIds={["invoice", "dashboard"]} />Long and Overflowing Results
The result panel has a capped logical block size and scrolls active options into view.
<CommandPalette open={open} onClose={close} items={manyCommands} />Global Shortcut Pattern
Register the global shortcut in the application and pass the resulting boolean to open.
The component intentionally does not install a global listener, preventing shortcut conflicts between applications.
useEffect(() => {
const openPalette = (event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
event.preventDefault();
setOpen(true);
}
};
document.addEventListener("keydown", openPalette);
return () => document.removeEventListener("keydown", openPalette);
}, []);API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Whether the modal palette is open |
onClose | () => void | - | Closes the palette after Escape, overlay dismissal, or selection |
items | CommandItem[] | - | Commands with id, label, callback, and optional keywords, section, icon, hotkey, or disabled state |
placeholder | string | "Search commands…" | Search input placeholder |
emptyMessage | ReactNode | "No commands found." | Content shown for an empty result |
filter | (item, query) => number | - | Custom ranker; scores at or below zero are excluded |
recentIds | string[] | [] | Commands pinned in Recent while the query is empty |
Ranking Function
rankCommandItem is exported for reuse and testing. Exact and prefix matches lead, followed by word-boundary, substring, and scattered subsequence matches.
RTL Support
Components automatically adapt to right-to-left languages using CSS logical properties.
Preview
Usage
<CommandPalette open={open} onClose={close} items={arabicCommands} />