A flexible, accessible command palette for React/Next.js applications, built with Tailwind CSS and Tabler Icons.
- 🎹 Global Shortcut: Toggle with
Ctrl+K(Windows/Linux) orCmd+K(Mac). - 🔌 Plug & Play: Easy integration via
CommandProvider. - ⚡ Dynamic Commands: Register and unregister commands at runtime from any component.
- 🎨 Themeable: Built with Tailwind CSS.
- ♿ Accessible: Keyboard navigation support.
Here's an overview of the project's file structure and the purpose of key directories:
src/
├── app/
│ ├── globals.css # Global styles and Tailwind directives
│ ├── layout.tsx # Root layout, wraps app with CommandProvider
│ └── page.tsx # Home page
├── components/
│ ├── AppCommands.tsx # Example component defining global app commands
│ └── CommandPalette/ # The core Command Palette component files
├── context/
│ └── CommandContext.tsx # Context provider for command state & logic
├── hooks/ # Custom hooks (e.g., useKeyPress)
└── stories/ # Storybook stories for UI testing
CommandContext.tsx: The brain of the operation. It manages theopen/closedstate and the list of registered registered commands. It provides theuseCommandPalettehook.AppCommands.tsx: A logical component that doesn't render anything visible but registers global commands (like "Go to Home", "Toggle Theme") when the app mounts.CommandPalette/: Contains the UI for the modal, search input, and command list.
This project is built with Next.js.
-
Install dependencies:
npm install # or yarn install -
Run the development server:
npm run dev
-
Start Storybook (Component Development):
npm run storybook
Open http://localhost:6006 to view your component library in isolation.
live link- https://fuzzy-search-with-react-l5pu.vercel.app/
Wrap your root layout or application component with CommandProvider:
import { CommandProvider } from '@/context/CommandContext';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<CommandProvider>
{children}
</CommandProvider>
</body>
</html>
);
}Use the useCommandPalette hook to register commands from any component. The AppCommands component demonstrates this:
import { useEffect } from 'react';
import { useCommandPalette } from '@/context/CommandContext';
import { IconHome } from '@tabler/icons-react';
export const MyComponent = () => {
const { registerCommand } = useCommandPalette();
useEffect(() => {
const unregister = registerCommand({
id: 'home',
label: 'Go to Home',
keywords: ['start', 'index'],
action: () => console.log('Navigating home...'),
icon: <IconHome />,
shortcut: ['G', 'H']
});
// Cleanup on unmount
return () => unregister();
}, [registerCommand]);
return null;
};- Next.js 15
- Tailwind CSS 4
- Tabler Icons