Install react-cmdk
mainInstall the package using npm or Yarn to start building your command palette.
npm install react-cmdkOr if you'd rather use Yarn
yarn add react-cmdkrepository·main·Indexed 20 days ago
https://github.com/albingroen/react-cmdkA fast, accessible, and pretty React.js command palette library for building high-performance, searchable UI overlays. It includes components like CommandPalette, Page, List, and ListItem, along with utilities for filtering JSON structures and a helper hook for implementing Cmd+K/Ctrl+K keyboard shortcuts.
Install the package using npm or Yarn to start building your command palette.
npm install react-cmdkyarn add react-cmdkYou can open the command palette using the provided helper hook or by implementing your own custom keyboard listener (e.g., for Cmd+K or Ctrl+K).
### Using the helper hook
```typescript
const [isOpen, setIsOpen] = useState<boolean>(false);
useHandleOpenCommandPalette(setIsOpen);const [isOpen, setIsOpen] = useState<boolean>(false);
useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
if (
(navigator?.platform?.toLowerCase().includes("mac")
? e.metaKey
: e.ctrlKey) &&
e.key === "k"
) {
e.preventDefault();
e.stopPropagation();
setIsOpen((currentValue) => {
return !currentValue;
});
}
}
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, []);This example demonstrates how to compose a command palette using CommandPalette, CommandPalette.Page, CommandPalette.List, and CommandPalette.ListItem. It also utilizes the filterItems and getItemIndex utilities to manage a searchable JSON structure of items.
import "react-cmdk/dist/cmdk.css";
import CommandPalette, { filterItems, getItemIndex } from "react-cmdk";
import { useState } from "react";
const Example = () => {
const [page, setPage] = useState<"root" | "projects">("root");
const [open, setOpen] = useState<boolean>(true);
const [search, setSearch] = useState("");
const filteredItems = filterItems(
[
{
heading: "Home",
id: "home",
items: [
{
id: "home",
children: "Home",
icon: "HomeIcon",
href: "#",
},
{
id: "settings",
children: "Settings",
icon: "CogIcon",
href: "#",
},
{
id: "projects",
children: "Projects",
icon: "RectangleStackIcon",
closeOnSelect: false,
onClick: () => {
setPage("projects");
},
},
],
},
{
heading: "Other",
id: "advanced",
items: [
{
id: "developer-settings",
children: "Developer settings",
icon: "CodeBracketIcon",
href: "#",
},
{
id: "privacy-policy",
children: "Privacy policy",
icon: "LifebuoyIcon",
href: "#",
},
{
id: "log-out",
children: "Log out",
icon: "ArrowRightOnRectangleIcon",
onClick: () => {
alert("Logging out...");
},
},
],
},
],
search
);
return (
<CommandPalette
onChangeSearch={setSearch}
onChangeOpen={setOpen}
search={search}
isOpen={open}
page={page}
>
<CommandPalette.Page id="root">
{filteredItems.length ? (
filteredItems.map((list) => (
<CommandPalette.List key={list.id} heading={list.heading}>
{list.items.map(({ id, ...rest }) => (
<CommandPalette.ListItem
key={id}
index={getItemIndex(filteredItems, id)}
{...rest}
/>
))}
</CommandPalette.List>
))
) : (
<CommandPalette.FreeSearchAction />
)}
</CommandPalette.Page>
<CommandPalette.Page id="projects">
{/* Projects page */}
</CommandPalette.Page>
</CommandPalette>
);
};
export default Example;CommandPalette is the root component. It manages the search state, open state, and current page navigation.CommandPalette.FreeSearchAction component provides a fallback action when no items match the search query. It extends HTMLAnchorElement & HTMLButtonElement types.CommandPalette.ListItem component represents an individual selectable item. It extends HTMLAnchorElement & HTMLButtonElement types.CommandPalette.List component groups items under a heading.CommandPalette.Page component allows you to organize content into different views. Using pages is optional.Props for the CommandPalette.Page component:
| name | type | required | default | description |
| ---------------- | ------------------------ | ---------------- | ---------------- | ----------------- |
| id | string | true | | A unique page id |
| children | React.ReactNode | true | | Children of the list |
| searchPrefix | string[] | false | | Prefix to the left of the search bar |
| onEscape | () => void | false | | Function that runs upon clicking escape |Props for the CommandPalette component:
| name | type | required | default | description |
| ---------------- | ------------------------ | ---------------- | ---------------- | --------------------------------- |
| onChangeSearch | (value: string) => void | true | | Function for setting search value |
| onChangeOpen | (value: boolean) => void | true | | Function for setting open state |
| children | React.ReactNode | true | | Children of command palette |
| isOpen | boolean | true | | Open state |
| search | string | true | | Search state |
| placeholder | string | false | `"Search"` | Search field placeholder |
| page | string | false | | The current page id |
| renderLink | RenderLink | false | | Function for customizing rendering of links |
| footer | React.ReactNode | false | | Footer component |
| selected | number | false | | The current selected item index |
| onChangeSelected | (value: number) => void | false | | Function for setting selected item index |Props for the CommandPalette.FreeSearchAction component:
| name | type | required | default | description |
| ---------------- | ------------------------ | ---------------- | ---------------- | ----------------- |
| index | number | false | `0` | Index for list item |
| label | string | false | `"Search for"` | Button label |