GithubHelp home page GithubHelp logo

albingroen / react-cmdk Goto Github PK

View Code? Open in Web Editor NEW
999.0 7.0 38.0 1.55 MB

A fast, accessible, and pretty command palette for React

Home Page: https://react-cmdk.com

License: MIT License

TypeScript 86.47% CSS 11.20% JavaScript 2.33%
react tailwindcss headlessui tsdx typescript

react-cmdk's Introduction

A command palette for React

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

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

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;

Opening the command palette

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(setIsOpen);

Custom

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

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

react-cmdk's People

Contributors

albingroen avatar buraksakalli avatar dshlass avatar imjared avatar lauthieb avatar mittnavnermike avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-cmdk's Issues

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'?

Items: Translations + expose item type

Hello, once again here:

Would be possible to add option to specify item type explicitly next to the used magic detection based on href? Because for example I'm on Next.js using router redirect instead of direct links, thus command pallete thinks it's an action, but in reality it's a link, so I can force it to render right type. Or use href='#' which I don't like.

Also it would be nice to accept a map with translations like {'Link': 'Link'} which could be translated from any client, for example using i18n on the user's (dev's) side. Now we do not have an access to those texts, so for example in Cz. it looks strange:

image

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar

Disable autoComplete on the Search field(input field) or make it controllable

Hello,

I genuinely dislike autoComplete features in annoying places. Therefore I would ask if u could make it permanently off or atleast programmable via props. The only place I noticed it was in the Search field(input field).

I can also look into it and mby make a pull request.

Thx for this component/library👍🏼

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar

Source Code for Website

Hi I am wondering how I go about implementing the cmd pallete with the bread crumb spacers, as seen on your website
image

The source code for this would be grately appreciated
Thanks!!

Upgrade to Heroicons v2?

Hello,

love ur package but are u considering to support heroicons v2 or custom Icons which aren't in heroicons v1?

Best Regards

Can we access the handler for theme change?

Can we access the handler for theme change? for dark and light

I think it would be useful.

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar

Uncaught TypeError with example component and React 18.18.2

Hi, i am facing an issue using react-cmdk with React 18.18.2. I get the following error in the browser console:

Uncaught TypeError: Cannot read properties of undefined (reading 'Child')
at CommandPalette (CommandPalette.tsx:162:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)

That's how my simple component looks like:

import "react-cmdk/dist/cmdk.css";
import CommandPalette from "react-cmdk";
import { useState } from "react";


const Cmdk = () => {
  const [isOpen, setIsOpen] = useState(false);
  const [search, setSearch] = useState("");

  return (
    <>
      <CommandPalette
        onChangeSearch={setSearch}
        onChangeOpen={setIsOpen}
        search={search}
        isOpen={isOpen}
        children=""
      >
        <CommandPalette.List heading="General">
          <CommandPalette.ListItem
            children="Home"
            icon="HomeIcon"
            index={0}
          />
        </CommandPalette.List>
      </CommandPalette>
    </>
  );
};

export default Cmdk;

What am i doing wrong?

How to style dark mode?

Hi there, I'm loving the library and how easy it is to use so far. I'm a little stuck on how to use and customize dark mode, can you help me out please?

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

Fuse.js for filtering

Instead of the custom filterItems fn, Fuse.js would be better. https://fusejs.io/

That is... if I know I want to find the term Collapse Sidebars I can usually just type something like col si into Fuse and it'll find the correct thing. Whereas with your custom filterItems fn, I'd have to type collapse si to get it over other Collapse ______ terms.

Async feature

Having an async mode with some loading props is something the package will accept?

[feature] Customize filtering

Currently the filtering of the search results with filterItems() are quite plain (it just filters with .includes() of the items array).

Adding a custom filtering function to filterItems() would be really nice, it could make it possible to do more complex filtering without the need to copy paste and adjust the filterItems function to your own codebase.

Background:
I am building a way to execute commands, like a function, but through the command palette. The function arguments are prompted to the user one by one, with options being displayed in the list as some kind of auto correction.
I want to add a way to select multiple options with a glob pattern and it would be nice to already preview all the matching options.

I don't want to reproduce the nested filtering logic that already is included in filterItems, so a custom filtering function would be quite handy.

[Suggestion]: Migrate to PBandJ

Given babel as a build tool isn't the most optimised and storybook v7 is in beta, it may make sense to migrate to PBandJ:

https://github.com/moishinetzer/pbandj

It also includes config for vitest, changesets for publishing and other modern features and tools

I'm happy to help make the transition if you need any help!

[Question]: Can I set my own Icons?

Hi,

I would like to set my own Icons I'm using in my system.

Can adapt the library to accept other Icons?

Thank you

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar

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?

Overly aggressive CSS selectors break components

Per the docs, an icon can take a React.FC. I'm trying to show a badge component that we use when we display projects. Normally this badge has its own styling included but it seems that it's blown away by some pretty aggressive rules:

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.