πŸ” A package with components for building your dream command palette for your web application.

Overview

A command palette for React

A package with components for building your dream command palette for your web application.

Features

βœ“ Accessible
βœ“ Flexible
βœ“ Good looking
βœ“ Very fast
βœ“ Dark & light mode

Installation

npm install react-cmdk

Or if you'd rather use Yarn

yarn add react-cmdk

Example usage

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.

{ const [page, setPage] = useState<"root" | "projects">("root"); const [open, setOpen] = useState(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: "CollectionIcon", closeOnSelect: false, onClick: () => { setPage("projects"); }, }, ], }, { heading: "Other", id: "advanced", items: [ { id: "developer-settings", children: "Developer settings", icon: "CodeIcon", href: "#", }, { id: "privacy-policy", children: "Privacy policy", icon: "SupportIcon", href: "#", }, { id: "log-out", children: "Log out", icon: "LogoutIcon", onClick: () => { alert("Logging out..."); }, }, ], }, ], search ); return ( {filteredItems.length ? ( filteredItems.map((list) => ( {list.items.map(({ id, ...rest }) => ( ))} )) ) : ( )} {/* Projects page */} ); }; export default Example;">
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: "CollectionIcon",
            closeOnSelect: false,
            onClick: () => {
              setPage("projects");
            },
          },
        ],
      },
      {
        heading: "Other",
        id: "advanced",
        items: [
          {
            id: "developer-settings",
            children: "Developer settings",
            icon: "CodeIcon",
            href: "#",
          },
          {
            id: "privacy-policy",
            children: "Privacy policy",
            icon: "SupportIcon",
            href: "#",
          },
          {
            id: "log-out",
            children: "Log out",
            icon: "LogoutIcon",
            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;

Opening the command palelette

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

const [isOpen, setIsOpen] = useState<boolean>(false);

useHandleOpenCommandPalette(setOpen);

Custom

{ return !currentValue; }); } } document.addEventListener("keydown", handleKeyDown); return () => { document.removeEventListener("keydown", handleKeyDown); }; }, []);">
const [isOpen, setIsOpen] = useState<boolean>(false);

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);
  };
}, []);

API

CommandPalette

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

CommandPalette.Page

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

CommandPalette.List

name type required default description
children React.ReactNode true Children of the list
heading string false Heading of the list

CommandPalette.ListItem

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
iconType IconType false "solid" Icon for list item
showType boolean false true Whether to show the item type
disabled boolean false Whether the item is disabled
keywords Array false Underlying search keywords for the list item

The list item also extends the HTMLAnchorElement & HTMLButtonElement types

CommandPalette.FreeSearchAction

name type required default description
index number false 0 Index for list item
label string false "Search for" Button label

The search action also extends the HTMLAnchorElement & HTMLButtonElement types

RenderLink

(
  props: DetailedHTMLProps<
    AnchorHTMLAttributes<HTMLAnchorElement>,
    HTMLAnchorElement
  >
) => ReactNode;

JsonStructure

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

JsonStructureItem

CommandPalette.ListItem

Omits index & extends

name type required default description
id string true Id for list item

Utils

getItemIndex

A function for getting the current index of a item within the json structure

(items: JsonStructure, listItemId: string, startIndex = 0) => number;

filterItems

A function for filtering the json structure from a search string

(
  items: JsonStructure,
  search: string,
  options?: { filterOnListHeading: boolean }
) => JsonStructure;

renderJsonStructure

A function for rendering a json structure

(items: JsonStructure) => JSX.Element[]

useHandleOpenCommandPalette

(fn: React.Dispatch<React.SetStateAction<boolean>>) => void

Maintainers

Comments
  • Navigation to previous commands.

    Navigation to previous commands.

    Whenever a user navigates to a command with sub-commands, there's nothing to tell the user to press the Escape key to go back. I think showing some sort of help message can make the user navigate back from deep sub-commands, without trying to figure out which key to press. This is a huge problem on mobile phones

    opened by lucky-chap 5
  • Microbundle error? No exported member

    Microbundle error? No exported member

    This looks awesome. Cloned the main branch to see if I could get it to work and after yarn install and then yarn start I'm getting this error

    Can you help

    (rpt2 plugin) Error: /Users/x/workspace/react-cmdk/src/index.tsx(5,10): semantic error TS2724: Module '"../node_modules/twind/twind"' has no exported member 'tw'. Did you mean 'TW'?
    
    opened by markojak 4
  • Styling and dark mode

    Styling and dark mode

    Hey, thanks for the library. I've managed to get things working with my own data fairly quickly.

    However, as far as I can tell, there is little to no way to hook into styling or even control dark mode β€” is this a limitation?

    opened by jpsear 2
  • Dark Mode not controllable

    Dark Mode not controllable

    Hello,

    first of all great project but I got 1 small problem.

    I want to have a theme toggle but since you have "darkMode": "media" in your tailwind.config.js this isn't posible.

    I wanted to ask if u could mby change it to some kind of env variable, since u obvioulsy can't access any kind of other app state and it won't make that much of a difference but for someone like me it would definitily help

    opened by OmegaHawkeye 2
  • Add support for hitting backspace to go up a page

    Add support for hitting backspace to go up a page

    Changes

    • Hitting Backspace when the search field is empty will run the onEscape function on the CommandPalette.Page component now.

    Demo

    https://user-images.githubusercontent.com/19674362/175822065-263f1014-bd33-415f-bb59-91426b04d935.mp4

    opened by albingroen 1
Owner
Albin Groen
Web developer, tinkerer, and Vim-lover
Albin Groen
Quickly load Vue, React, SpriteJS components via command line

Faster way to render & interact react & vue3 components with command line interface.

η¨€εœŸ 6 Mar 9, 2022
semantic-release automates the whole package release workflow including: determining the next version number, generating the release notes, and publishing the package.

?? ?? semantic-release Fully automated version management and package publishing semantic-release automates the whole package release workflow includi

null 16.5k Oct 2, 2022
Write down a shell command-line to see how it works in details.

shell.how Write down a shell command-line to see how it works in details. Design Stack TypeScript Next.js Tailwind CSS Recoil for state management, it

Minh-Phuc Tran 225 Oct 3, 2022
Trong ORM is a JavaScript library for building reactive SQLite queries for web, mobile and desktop

Trong ORM is a JavaScript library for building reactive SQLite queries for web, mobile and desktop

null 66 Sep 25, 2022
React-NFT-App - NFT-Web-Application built using Third web , ReactJs and use Crypto Punks with API

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Ali Aftab Sheikh 7 Aug 17, 2022
Repo for the react-borders NPM package.

React Borders Basic Usage You can attach a border to an element using the border component exported from react-borders. The below code will generate a

null 3 Mar 11, 2022
Package library for common React functionalities.

Primors Package library for common React functionalities. Live documentation Storybook docs deployed on GH Pages: https://dagerikhl.github.io/primors

Dag Erik LΓΈvgren 2 Jul 28, 2022
Firerr - A package for catching Firebase Errors that often pop in development

FirErr FirErr is a package for catching Firebase Errors that often pop in develo

Ihsan Fashbir 2 Feb 28, 2022
Use js to download and unzip the npm package. only supports use in the browser.

Use js to download and unzip the npm package. only supports use in the browser.

Arthur 8 Sep 29, 2022
whatscode.js is a package to create Whatsapp bots easily and quickly, even coding experience is not really needed...

whatscode.js is a package to create Whatsapp bots easily and quickly, even coding experience is not really needed...

JstnLT 20 Sep 21, 2022
A guide to building your own React stack, explaining options and tradeoffs along the way

Custom React Stack React has a very rich ecosystem. For anything you want to do, there is probably a library or a framework available for it. That's g

Naresh Bhatia 13 Aug 10, 2022
We have updated our application over to using hooks and functional components to replace any class components we had before.

Crwn hooks We have updated our application over to using hooks and functional components to replace any class components we had before. How to fork an

Shazil Sattar 2 Feb 10, 2022
my-watchlist is a web application for creating your own watchlist.

my-watchlist is a web application for creating your own watchlist. The website tracks your created watchlist, so that you can comeback anytime and pick from where you left.

Ashish Poudel 4 Jun 25, 2022
The react UI component for building complex filter criteria

React Filter Control The React component for building the composite filter criteria Demo (JS) | Demo (TS) Together With Data Table Overview Installati

Alexander Komarov 32 Sep 24, 2022
A powerful toolkit for building websites with beautiful design

Typography.js A powerful toolkit for building websites with beautiful typography. Typography.js A powerful toolkit for building websites with beautifu

Kyle Mathews 3.7k Sep 28, 2022
:fire: An extremely fast, React-like JavaScript library for building modern user interfaces

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server. Description The main obje

Inferno 15.6k Sep 26, 2022
The LinkedIn Learning course React.js: Building an Interface

React.js: Building an Interface This is the repository for the LinkedIn Learning course React.js: Building an Interface. The full course is available

MOHAMMED KHORMI 1 Oct 14, 2021
Node.js library for building systematic trading strategies in reactive way.

Node.js library for building systematic trading strategies in reactive way. Use the power of TypeScript and Reactive Programming to research, develop

null 2 Dec 22, 2021
Code demo from "Building Design Systems With React" talk

React Button This repository is the code demo from my "Building Design Systems With React" talk I will give at ReactJS Girls London. I will link the d

Emma Bostian 51 May 29, 2022