A fast, accessible, and pretty React.js command palette
npm install @tmikeladze/react-cmdk
A package with components for building your dream command palette for your web application.
Watch the YouTube demo or try it out here to get started.
- Features
- Installation
- Example usage
- Opening the commane palelette
- API
- Utils
- Maintainers
✓ Accessible
✓ Flexible
✓ Good looking
✓ Very fast
✓ Dark & light mode
```
npm install react-cmdk
Or if you'd rather use Yarn
``
yarn add react-cmdk
You can compose your command palette pretty much however you like with the
included components. But here is an example of a command palette that uses some
of the included helpers for a very neat solution.
`typescript
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
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 (
onChangeOpen={setOpen}
search={search}
isOpen={open}
page={page}
>
{filteredItems.length ? (
filteredItems.map((list) => (
{list.items.map(({ id, ...rest }) => (
index={getItemIndex(filteredItems, id)}
{...rest}
/>
))}
))
) : (
)}
{/ Projects page /}
);
};
export default Example;
`
The package does include a helper hook for opening the command palette,
but you can actually open it however you want. Here are some examples.
#### Helper
`typescript
const [isOpen, setIsOpen] = useState
useHandleOpenCommandPalette(setIsOpen);
`
#### Custom
`typescript
const [isOpen, setIsOpen] = useState
useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
if (e.metaKey && e.key === "k") {
e.preventDefault();
e.stopPropagation();
setIsOpen((currentValue) => {
return !currentValue;
});
}
}
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, []);
`
| 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 |
FYI. Using pages is completely optional
| 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 |
| name | type | required | default | description |
| -------- | --------------- | -------- | ------- | -------------------- |
| children | React.ReactNode | true | | Children of the list |
| heading | string | false | | Heading of the list |
| name | type | required | default | description |
| ------------- | -------------------- | -------- | ---------- | ----------------------------------------------- |
| index | number | true | | Index for list item |
| closeOnSelect | boolean | false | | Whether to close the command palette upon click |
| icon | (IconName, React.FC) | false | false | Icon for list item |"solid"
| iconType | IconType | false | | Icon for list item |
| showType | boolean | false | true | Whether to show the item type |
| disabled | boolean | false | | Whether the item is disabled |
| keywords | Array
The list item also extends the HTMLAnchorElement & HTMLButtonElement types
| name | type | required | default | description |
| ----- | ------ | -------- | -------------- | ------------------- |
| index | number | false | 0 | Index for list item |"Search for"
| label | string | false | | Button label |
The search action also extends the HTMLAnchorElement & HTMLButtonElement types
`typescript`
(
props: DetailedHTMLProps<
AnchorHTMLAttributes
HTMLAnchorElement
>
) => ReactNode;
Array of
| name | type | required | default | description |
| ------- | -------------------------- | -------- | ------- | ---------------- |
| id | string | true | | Id for list |
| items | Array<JsonStructureItem> | true | | Items for list |
| heading | string | false | | Heading for list |
CommandPalette.ListItem
Omits index & extends
| name | type | required | default | description |
| ---- | ------ | -------- | ------- | ---------------- |
| id | string | true | | Id for list item |
A function for getting the current index of a item within the json structure
`typescript`
(items: JsonStructure, listItemId: string, startIndex = 0) => number;
A function for filtering the json structure from a search string
`typescript`
(
items: JsonStructure,
search: string,
options?: { filterOnListHeading: boolean }
) => JsonStructure;
A function for rendering a json structure
`typescript`
(items: JsonStructure) => JSX.Element[]
`typescript``
(fn: React.Dispatch