image

kmenu

๐ŸŒˆ Animated and accessible cmdk interface

Demo ยท NPM ยท Product Hunt ยท StackBlitz ยท CodeSandbox

๐Ÿš€ Quickstart

Install the npm package

yarn add kmenu

Adding commands

After you’ve installed the package, you can now begin adding commands onto the command palette.

Here’s a look at how you can create commands:

Parameter Description Type Optional
icon The icon displayed next to the command ReactElement โœ…
text The text displayed on the command String โŒ
perform The action to perform void โœ…
href The link to open void โœ…
newTab Whether or not the link should open in a new tab boolean โœ…
keywords Search keywords for the command string โœ…
category The category this command will go under string โŒ

Here’s an example of how to create the commands (using TypeScript):

import {
  Search,
  Copy,
  Globe,
  GitHub,
  AlertCircle,
  GitPullRequest,
  Zap,
  Edit2,
  Plus,
  Settings,
  Code,
  Command as Cmd,
  Terminal
} from 'react-feather'
import type { Command } from 'kmenu'

const commands: Command[] = [
  {
    icon: <Search />,
    text: 'Search Documentation...',
    keywords: 'docs',
    category: 'Utility',
    perform: () => /* function */
  },
  {
    icon: <Copy />,
    text: 'Copy URL',
    perform: () => /* function */,
    category: 'Utility'
  },
  {
    icon: <Globe />,
    text: 'Demo',
    href: 'https://kmenu.hxrsh.in',
    keywords: 'homepage site web',
    category: 'Links'
  },
  {
    icon: <GitHub />,
    text: 'GitHub',
    href: 'https://github.com/harshhhdev/kmenu',
    keywords: 'source',
    category: 'Links'
  },
  {
    icon: <AlertCircle />,
    text: 'Issues',
    href: 'https://github.com/harshhhdev/kmenu/issues',
    keywords: 'source',
    category: 'Links'
  },
  {
    icon: <GitPullRequest />,
    text: 'Pull Requests',
    href: 'https://github.com/harshhhdev/kmenu/pulls',
    keywords: 'source',
    category: 'Links'
  }
]

Customising the Palette

You can easily customise the colours on your command palette as well. Here’s a list of properties that are customisable:

NOTE: ALL PROPERTIES ARE OPTIONAL

Parameter Description Type Default
paletteMaxHeight The max height of the palette (px) number 320
backdropColor The colour of the backdrop (include opacity) string #00000020
backdropBlur The backround blur of the backdrop (px) number 5px
backgroundColor The background colour of the palette string #181818
borderWidth Width of the border surrounding the palette number 1px
borderColor The colour of the border surrounding the palette string #3F3F3F
borderRadius The radius of the palette (px) number 16px
inputColor The colour of the text in the search bar string #FFFFFF
placeholderText The placeholder input text in the search bar string ‘What do you need?’
headingColor The colour of the command category headings string #777777
commandInactive The colour of the icon and text when the command is inactive string #777777
commandActive The colour of the icon and text when the command is active string #FFFFFF
barBackground The background colour of the active bar (include opacity) string #FFFFFF20

Setting up the palette

Here are all the options available on the palette:

Parameter Description Type Optional
open The index of which palette is currently open number โŒ
setOpen The hook to handle the state for which palette is currently open Dispatch<SetStateAction> โŒ
index The index of this palette number โŒ
commands The commands for this palette to display Command[] โŒ
categories The categories which the commands have been assigned to string[] โŒ
config The configuration for this colour palette PaletteConfig โœ…
main Whether or not this is the first palette that’ll be displayed boolean โœ…

Once you have added commands to the palette and configured it to you likings, you can add it into your application. Add in the CSS file for styling. Optionally, if you’d like to FULLY customise the styles on the palette to your likings then you can copy the index.css file from the repository and import that instead. You’ll also need to create a useState hook for handling the state.

import { useState } from 'react'
import { Palette, Command, PaletteConfig } from 'kmenu'
import 'kmenu/dist/index.css'

const Component = () => {
  const [open, setOpen] = useState(0)

  const commands: Command[] = [ /* ... */ ]
  const config: PaletteConfig = { /* ... */ }
  const categories: string[] = [ /* ... */ ]

  return (
    /* ... */
    <Palette
      open={open}
      setOpen={setOpen}
      index={1}
      commands={commands}
      config={config}
      categories={categories}
      main
    />
    /* ... */
  )
}
// ...
export default Component

That’s about all the configuration you’ll need to do in order to get a basic command palette to work!

Nested Palettes

This library also provides support for nested palettes and commands. Here’s an example to help you out:

import { useState } from 'react'
import Palette, { Command, PaletteConfig } from 'kmenu'
import 'kmenu/dist/index.css'

const Palette = () => {
  const [open, setOpen] = useState(0)

  const mainCommands: Command[] = [
    {
      icon: <FiGlobe />,
      text: 'Website',
      href: 'https://hxrsh.in',
      newTab: true,
      keywords: 'home',
      category: 'Socials'
    },
    {
      icon: <FiArrowRight />,
      text: 'Nested Example...',
      perform: () => setOpen(2),
      category: 'Utility'
    },
  ]

  const nestedExample: Command[] = [
    {
      icon: <FiGlobe />,
      text: 'Demo',
      href: 'https://kmenu.hxrsh.in',
      newTab: true,
      keywords: 'home',
      category: 'Resources'
    },
    {
      icon: <FiGlobe />,
      text: 'GitHub',
      href: 'https://github.com/harshhhdev/kmenu',
      newTab: true,
      keywords: 'source',
      category: 'Resources'
    },
  ]

  const config: PaletteConfig = { /* ... */ }
  const categories: string[] = [ /* ... */ ]

  return (
    /* ... */
    <Palette
      open={open}
      setOpen={setOpen}
      index={1}
      commands={mainCommands}
      config={config}
      categories={categories}
      main
    />
    <Palette
      open={open}
      setOpen={setOpen}
      index={2}
      commands={nestedExample}
      config={config}
      categories={categories}
    />
    /* ... */
  )
}
// ...
export default Palette

If this isn’t enough, there’s also an example directory which you can clone and experiment around with to build nested routes!

Using the useShortcut hook

This library also ships with a custom React hook called useShortcut which you can use to define your own shortcuts within your application.

Parameter Description Type Optional
targetKey The key that the shortcut is listening for string (must be valid key) โŒ
modifier The modifier key which can will activate the shortcut enum (shift/alt/ctrl) โœ…

Here’s an example:

import { useShortcut } from 'kmenu'

const Palette = () => {
  const shiftS = useShortcut('s', 'shift')

  // ...
}
// ...
export default Palette

The example below will run when someone uses the keyboard shortcut shift+s.

๐Ÿ’ป Development

Run the project locally

git clone https://github.com/harshhhdev/kmenu.git

Setting up the project

cd kmenu

# Install dependencies
yarn

Next, start the development server:

yarn start

This should compile an instance of your project to the dist folder. It should re-build everytime you save a new change.

Using the package

You can test the built package locally by running the example repository:

cd example

# Install dependencies
yarn

# Start development server
yarn start

Awesome. Your React development server should now be running on port 3000.

๐Ÿ”ง Tools Used

๐Ÿคž Contributing

After setting up the project, and making changes:

git add .
git commit -m "commit message"
git push YOUR_REPO_URL YOUR_BRANCH

Inspirations

GitHub

View Github