react-cmdk

repository·main·Indexed 20 days ago

https://github.com/albingroen/react-cmdk

A 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.

Tokens
8.2K
Snippets
13
Records
33
Agent score
79%

What's inside react-cmdk

  1. How to open the command palette

    main

    You 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);

    Using a custom keyboard listener

    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);
      };
    }, []);
  2. Example usage of react-cmdk

    main

    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;
  3. CommandPalette.Page Props

    main

    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 |
  4. CommandPalette Props

    main

    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 |
  5. CommandPalette.FreeSearchAction Props

    main

    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 |