kbar

fast, portable, and extensible cmd+k interface for your site

README

kbar


kbar is a simple plug-n-play React component to add a fast, portable, and extensible command + k (command palette) interface to your site.

demo

Background


Command + k interfaces are used to create a web experience where any type of action users would be able to do via clicking can be done through a command menu.

With macOS's Spotlight and Linear's command + k experience in mind, kbar aims to be a simpleabstraction to add a fast and extensible command + k menu to your site.

Features


- Built in animations and fully customizable components
- Keyboard navigation support; e.g. control + n or control + p for the navigation wizards- Keyboard shortcuts support for registering keystrokes to specific actions; e.g. hit t for Twitter, hit ? to immediate bring up documentation search
- Nested actions enable creation of rich navigation experiences; e.g. hit backspace to navigate to
  the previous action
- Performance as a first class priority; tens of thousands of actions? No problem.
- History management; easily add undo and redo to each action
- Built in screen reader support
- A simple data structure which enables anyone to easily build their own custom components

Usage


Have a fully functioning command menu for your site in minutes. First, install kbar.

  1. ```
  2. npm install kbar
  3. ```

There is a single provider which you will wrap your app around; you do not have to wrap your
_entire_ app; however, there are no performance implications by doing so.

  1. ```tsx
  2. // app.tsx
  3. import { KBarProvider } from "kbar";

  4. function MyApp() {
  5.   return (
  6.     <KBarProvider>
  7.       // ...
  8.     </KBarProvider>
  9.   );
  10. }
  11. ```

Let's add a few default actions. Actions are the core of kbar – an action define what to execute
when a user selects it.

  1. ```tsx
  2.   const actions = [
  3.     {
  4.       id: "blog",
  5.       name: "Blog",
  6.       shortcut: ["b"],
  7.       keywords: "writing words",
  8.       perform: () => (window.location.pathname = "blog"),
  9.     },
  10.     {
  11.       id: "contact",
  12.       name: "Contact",
  13.       shortcut: ["c"],
  14.       keywords: "email",
  15.       perform: () => (window.location.pathname = "contact"),
  16.     },
  17.   ]

  18.   return (
  19.     <KBarProvider actions={actions}>
  20.       // ...
  21.     </KBarProvider>
  22.   );
  23. }
  24. ```

Next, we will pull in the provided UI components from kbar:

  1. ```tsx
  2. // app.tsx
  3. import {
  4.   KBarProvider,
  5.   KBarPortal,
  6.   KBarPositioner,
  7.   KBarAnimator,
  8.   KBarSearch,
  9.   useMatches,
  10.   NO_GROUP
  11. } from "kbar";

  12. // ...
  13.   return (
  14.     <KBarProvider actions={actions}>
  15.       <KBarPortal> // Renders the content outside the root node
  16.         <KBarPositioner> // Centers the content
  17.           <KBarAnimator> // Handles the show/hide and height animations
  18.             <KBarSearch /> // Search input
  19.           </KBarAnimator>
  20.         </KBarPositioner>
  21.       </KBarPortal>
  22.       <MyApp />
  23.     </KBarProvider>;
  24.   );
  25. }
  26. ```

At this point hitting cmd+k (macOS) or ctrl+k (Linux/Windows) will animate in a search input and nothing more.

kbar provides a few utilities to render a performant list of search results.

- useMatches at its core returns a flattened list of results and group name based on the current
  search query; i.e. ["Section name", Action, Action, "Another section name", Action, Action]
- KBarResults renders a performant virtualized list of these results

Combine the two utilities to create a powerful search interface:

  1. ```tsx
  2. import {
  3.   // ...
  4.   KBarResults,
  5.   useMatches,
  6.   NO_GROUP,
  7. } from "kbar";

  8. // ...
  9. //
  10. //  
  11. <RenderResults />;
  12. // ...

  13. function RenderResults() {
  14.   const { results } = useMatches();

  15.   return (
  16.     <KBarResults
  17.       items={results}
  18.       onRender={({ item, active }) =>
  19.         typeof item === "string" ? (
  20.           <div>{item}</div>
  21.         ) : (
  22.           <div
  23.             style={{
  24.               background: active ? "#eee" : "transparent",
  25.             }}
  26.           >
  27.             {item.name}
  28.           </div>
  29.         )
  30.       }
  31.     />
  32.   );
  33. }
  34. ```

Hit cmd+k (macOS) or ctrl+k (Linux/Windows) and you should see a primitive command menu. kbar allows you to have full control over allaspects of your command menu – refer to the docs to get
an understanding of further capabilities. Looking forward to see what you build.

Used by


Listed are some of the various usages of kbar in the wild – check them out! Create a PR to add your
site below.


Contributing to kbar


Contributions are welcome!

New features


Please open a new issue so we can discuss prior to moving
forward.

Bug fixes


Please open a new Pull Request for the given bug fix.

Nits and spelling mistakes


Please open a new issue for things like spelling mistakes
and README tweaks – we will group the issues together and tackle them as a group. Please do not
create a PR for it!