reakeys

⌨️ React Hotkeys Hook

Showing:

Popularity

Downloads/wk

2K

GitHub Stars

30

Maintenance

Last Commit

1mo ago

Contributors

0

Package

Dependencies

1

License

Apache-2.0

Type Definitions

Built-In

Tree-Shakeable

Yes?

Categories

Readme

⌨️ reakeys


React Hook for Mousetrap Hotkeys


📦 Usage

Install via NPM:

yarn add reakeys

Then in your component, just add the useHotkeys hook and specify your keys like:

import React, { FC } from 'react';
import { useHotkeys } from 'reakeys';

export const YourComponent: FC = () => {
  useHotkeys([
    {
      name: 'Dashboard',
      keys: 'mod+shift+d',
      category: 'Navigation',
      callback: event => {
        event.preventDefault();
        history.push('/dashboard');
      }
    }
  ]);
};

Below are the options you can set in the hook array:

type HotkeyShortcuts = {
  name: string;
  category?: string;
  description?: string;
  keys: string | string[];
  ref?: any;
  hidden?: boolean;
  callback: (e: ExtendedKeyboardEvent, combo: string) => void;
}

You can also get all the hotkeys that registered by just calling the useHotkeys hook and it will return the current hotkeys.

const hotkeys = useHotkeys();

This is useful for creating a dialog to present the user with all the options. Below is an example of how to make a dialog using realayers:

import React, { useState, FC, useCallback } from 'react';
import { Dialog } from 'shared/Dialog';
import { useHotkeys } from 'reakeys';
import groupBy from 'lodash/groupBy';
import sortBy from 'lodash/sortBy';

const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;

export const HotkeyCombos: FC = () => {
  const hotkeys = useHotkeys();
  const categories = groupBy(hotkeys, 'category');

  const sorted = Object.keys(categories).reduce((prev, cur) => {
    const category = sortBy(categories[cur], 'name');
    const label = cur === 'undefined' ? 'General' : cur;

    return {
      ...prev,
      [label]: category.filter(k => !k.hidden)
    };
  }, {});

  const { General, ...rest } = sorted as any;
  const others = sortBy(Object.keys(rest || {}));

  const renderKeyCode = useCallback(keyCode => {
    const wrapped = Array.isArray(keyCode) ? keyCode : [keyCode];
    const formatted = wrapped.map(k => k.replace('mod', isMac ? '⌘' : 'CTRL'));

    return (
      <div className={css.keyComboContainer}>
        {formatted.map((k, i) => (
          <kbd key={i} className={css.keyCombo}>
            {k}
          </kbd>
        ))}
      </div>
    );
  }, []);

  const renderGroups = useCallback(
    group => {
      if (!sorted[group]) {
        return null;
      }

      return (
        <div key={group}>
          <h3>{group}</h3>
          <ul className={css.list}>
            {sorted[group].map(kk => (
              <li key={kk.name} className={css.listItem}>
                <label>{kk.name}</label>
                {renderKeyCode(kk.keys)}
                {kk.description && <p>{kk.description}</p>}
              </li>
            ))}
          </ul>
        </div>
      );
    },
    [renderKeyCode, sorted]
  );

  return (
    <div className={css.groups}>
      {renderGroups('General')}
      {others.map(renderGroups)}
    </div>
  );
};

export const HotkeyDialog: FC = () => {
  const [visible, setVisible] = useState<boolean>(false);

  useHotkeys([
    {
      name: 'Hotkey Dialog',
      keys: 'SHIFT+?',
      hidden: true,
      callback: () => setVisible(true)
    }
  ]);

  return (
    <Dialog
      size="800px"
      header="Hotkeys"
      open={visible}
      onClose={() => setVisible(false)}
    >
      {() => <HotkeyCombos />}
    </Dialog>
  );
};

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100
No reviews found
Be the first to rate

Alternatives

No alternatives found

Tutorials

No tutorials found
Add a tutorial