A lightweight, customizable command palette component for React & Next.js.
Provides a beautiful, accessible command palette with full theming support, custom keybinds, and smart search filtering.
- π― Simple API - Pass items directly without wrapper components
- π¨ Full Customization - Control colors, fonts, radius, spacing
- π Dark & Light Mode - Built-in theme presets with overrides
- β¨οΈ Custom Keybinds - Define your own keyboard shortcuts
- π Link & Action Items - Support navigation links and callbacks
- π Smart Search - Filter by label, group, or keywords
- βΏ Accessible - ARIA labels, keyboard navigation
- πͺΆ No Dependencies - Only requires React 18+
- β‘ Lightweight - ~14KB unminified, ~3.5KB gzipped
npm install @zacaw99/cmdbarFor Next.js with Server and Client Components, create a Client Component wrapper:
// app/components/CommandPalette.tsx
"use client";
import { CmdBar, type CmdBarItem } from "@zacaw99/cmdbar";
const items: CmdBarItem[] = [
{
id: "home",
label: "Home",
group: "Navigation",
href: "/",
},
{
id: "logout",
label: "Logout",
group: "Account",
onSelect: () => {
// Handle logout
},
},
];
export function CommandPalette() {
return <CmdBar items={items} />;
}Then use in your Server Component layout:
// app/layout.tsx
import { CommandPalette } from "./components/CommandPalette";
export default function RootLayout({ children }) {
return (
<html>
<body>
<CommandPalette />
{children}
</body>
</html>
);
}Benefits:
- π₯οΈ Server Component layout stays on the server
- β‘ Minimal client JavaScript
- π Keep sensitive logic server-side
- β¨ Best performance
For standalone React applications (Vite, Create React App, etc.):
// src/App.tsx
import { CmdBar, type CmdBarItem } from "@zacaw99/cmdbar";
const items: CmdBarItem[] = [
{
id: "home",
label: "Home",
group: "Navigation",
href: "/",
},
{
id: "settings",
label: "Settings",
group: "Account",
onSelect: () => {
// Handle settings
},
},
{
id: "logout",
label: "Logout",
group: "Account",
onSelect: () => {
// Handle logout
},
},
];
export default function App() {
return (
<div>
<CmdBar items={items} />
{/* Your app content */}
</div>
);
}Usage with Vite:
npm install @zacaw99/cmdbarImport in your component and pass items directly. Works everywhere React runs!
| Prop | Type | Default | Description |
|---|---|---|---|
items |
CmdBarItem[] |
Placeholder | Array of command items |
placeholder |
string |
"Type a command..." |
Input placeholder text |
emptyText |
string |
"No commands found." |
Empty state text |
closeOnSelect |
boolean |
true |
Close after selecting item |
keybind |
KeyBindConfig | false |
{ key: "k", ctrlKey: true, metaKey: true } |
Keyboard shortcut config |
theme |
CmdBarTheme |
dark |
Theme configuration |
type CmdBarActionItem = {
id: string;
label: string;
group?: string;
keywords?: string[];
icon?: ReactNode;
disabled?: boolean;
onSelect: () => void;
};
type CmdBarLinkItem = {
id: string;
label: string;
group?: string;
keywords?: string[];
icon?: ReactNode;
disabled?: boolean;
href: string;
};
type CmdBarItem = CmdBarActionItem | CmdBarLinkItem;<CmdBar
items={items}
keybind={{
key: "p",
ctrlKey: true,
shiftKey: true,
}}
/>Disable keybind:
<CmdBar
items={items}
keybind={false}
/>Dark mode (default):
<CmdBar
items={items}
theme={{ mode: "dark" }}
/>Light mode:
<CmdBar
items={items}
theme={{ mode: "light" }}
/>Custom colors:
<CmdBar
items={items}
theme={{
colors: {
background: "#1e1e1e",
text: "#ffffff",
itemSelected: "rgba(255, 255, 255, 0.12)",
border: "rgba(255, 255, 255, 0.1)",
},
}}
/>Full theme configuration:
type CmdBarTheme = {
mode?: "light" | "dark";
colors?: {
overlay?: string;
background?: string;
border?: string;
text?: string;
textSecondary?: string;
itemHover?: string;
itemSelected?: string;
};
radius?: {
panel?: number | string;
item?: number | string;
};
fonts?: {
family?: string;
size?: {
input?: number | string;
label?: number | string;
groupLabel?: number | string;
meta?: number | string;
};
weight?: { normal?: number; bold?: number };
};
spacing?: {
padding?: number | string;
gap?: number | string;
};
};Access state and controls from any Client Component:
"use client";
import { useCmdBar } from "@zacaw99/cmdbar";
export function MyComponent() {
const { isOpen, query, toggle, setQuery } = useCmdBar();
return <button onClick={toggle}>Toggle CmdBar</button>;
}import { cmdbar } from "@zacaw99/cmdbar";
cmdbar.open();
cmdbar.close();
cmdbar.toggle();
cmdbar.setQuery("search");
cmdbar.clearQuery();- Cmd+K (Mac) / Ctrl+K (Windows/Linux) - Toggle palette
- β/β - Navigate items
- Enter - Select item
- Escape - Close palette
CmdBar uses a store-based state management approach with a minimal client footprint. Always wrap interactive items in a Client Component wrapper to keep your layout as a Server Component.
Why?
- Preserves server-side capabilities (metadata, database queries)
- Minimal client JavaScript
- Better performance
- Clear separation of concerns
import { Home, Settings, LogOut } from "lucide-react";
const items: CmdBarItem[] = [
{
id: "home",
label: "Home",
icon: <Home size={16} />,
href: "/",
},
{
id: "settings",
label: "Settings",
icon: <Settings size={16} />,
href: "/settings",
},
];const items: CmdBarItem[] = [
{ id: "home", label: "Home", group: "Navigation", href: "/" },
{ id: "about", label: "About", group: "Navigation", href: "/about" },
{ id: "new", label: "Create", group: "Actions", onSelect: () => {} },
{ id: "settings", label: "Settings", group: "Settings", onSelect: () => {} },
];const items: CmdBarItem[] = [
{
id: "admin",
label: "Admin Panel",
href: "/admin",
disabled: !isAdmin,
},
];- Chrome/Edge: Latest
- Firefox: Latest
- Safari: Latest (14+)
- Mobile browsers: Full support
MIT
Created by zacaw99