CommandPalette
Always-visible searchable command palette with keyboard shortcut hints. Filter items by typing.
Use and inspectUse this pattern for the stated interaction and keep its keyboard path visible. Reset preview remounts the local example; it does not establish production persistence or a backend integration. Add a reduced-motion fallback where the source animates.Next: inspect the source and adapt its event or data boundary.
CommandPaletteAlways-visible searchable command palette with keyboard shortcut hints. Filter items by typing.
"use client";
import { useState } from "react";
export type CommandItem = {
icon?: string;
label: string;
kbd?: string;
};
type CommandPaletteProps = {
items: CommandItem[];
placeholder?: string;
onSelect?: (item: CommandItem) => void;
};
export function CommandPalette({
items,
placeholder = "Search commands...",
onSelect,
}: CommandPaletteProps) {
const [query, setQuery] = useState("");
const filtered = query
? items.filter((i) => i.label.toLowerCase().includes(query.toLowerCase()))
: items;
return (
<div className="sk-cmd">
<div className="sk-cmd-search">
<span className="sk-cmd-search-icon">⌘</span>
<input
className="sk-cmd-input"
placeholder={placeholder}
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
</div>
<div className="sk-cmd-results">
{filtered.map((item, i) => (
<button key={i} className="sk-cmd-item" onClick={() => onSelect?.(item)}>
{item.icon && <span className="sk-cmd-icon">{item.icon}</span>}
<span className="sk-cmd-label">{item.label}</span>
{item.kbd && <kbd className="sk-cmd-kbd">{item.kbd}</kbd>}
</button>
))}
</div>
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
items* | CommandItem[] | — | Array of command items with optional icon and kbd |
placeholder | string | "Search commands..." | Input placeholder |
onSelect | (item: CommandItem) => void | — | Called when an item is clicked |