Introduction
Using hotkeys is a great way to let your web app users get more done faster.
It works even better for power users and complex internal applications where your users spend a lot of time, like systems for content editing, monitoring systems or support tools.
In this article, first, we'll look at some design aspects to keep in mind when implementing hotkeys in an app and ways to make hotkeys convenient for the end user. Then we will do basic hotkeys implementation and look at how to add hotkeys to React application.
Hotkey Integration Preparations
Stick to three hotkey development guidelines:
- Discoverability: familiarise your users with hotkeys. Use onboarding, walkthroughs, labels or tooltips to help users learn about your hotkeys system
- Memorability: hotkeys and key combos need to be simple and memorable
- Compatibility: avoid situations where your hotkeys conflict with existing system-wide or browser shortcuts
1. Make a Plan
Define a list of actions demanding hotkey implementation. It is helpful to pursue a structured approach, starting with mapping out the user stories in your application and defining app sections. Then split your user stories into actions ranked by importance and usage frequency. Leveraging user feedback and analytics can be very helpful here. All the actions could be divided in two big groups:
Global actions include navigation between app parts and launching important functionality. Generally, it makes sense to implement it on the top level of the app (e.g. as a react wrapper component or context).
Contextual actions, such as controlling modal windows or popups, should be implemented at the relevant component level (modal window, multi-step form, etc.).
2. Pick the Hotkeys
Think of the hotkeys and key combos. Remember that they should be memorable and non-conflicting with browser or OS hotkeys.
Keep context and users in mind. What OS they are using, other running apps, preferred browser hotkeys, such as native browser search for content-rich websites.
Steer clear of the overloaded classic key combos
Ctrl + N, Ctrl + O, Ctrl + S, Ctrl + P, Ctrl + W & Ctrl + C, Ctrl + Z, Ctrl + F
Alt + F1, F2, F3…-
Decide if you want to use
- Single hotkeys
- Combinations or
- Sequences - keep in mind that they should not conflict with single hotkeys
Settling on one approach will simplify hotkeys for the users.
Single-key hotkeys are easier to use and remember, especially if they're assigned to actions corresponding with key letters. However, this allows for accidental keypresses and a smaller number of possible hotkeys. There are more options with combinations, but some of them will be already used by OS and browser hotkeys.
The sequences approach works for assigning lots of actions, giving you the biggest freedom of options and number of available combos. For example, it’s used in Gmail. But if you pick this route, avoid using single hotkeys since that will lead to conflicts and a poor UX. You can override browser hotkeys by calling event.preventDefault()
but think twice before you do it as it can be super annoying to your users sometimes.
After deciding what hotkeys you will assign to your actions, go to your app and try to use them as if they are already there. This will put you in users' shoes and let you identify what works well and what could be improved.
3. Think About Informing the User
Find a way to implement hotkey information in your design. Some of the frequently used tools include:
Labels
Tooltips
Underlined letters in buttons corresponding to hotkeys
Hotkey maps
For the best discoverability and memorability, it’s great to add a hotkey map, i.e. a page or a modal window with the list of all available actions in the app.
If there are many hotkeys, a search with a filter may be added on top of the map. Here are some examples of hotkey maps:
By the way, in all the examples above, users can see those hotkey maps by hitting a '?' key. You can consider following this best practice as well.
As a result, you have a list of hotkeys and informational design elements to get users up to speed. Now we can move on to implementation.
For internal app interfaces, which users think of as their main work tools, consider making hotkeys customisable so that users can reassign the keys. This could be useful for the most advanced users.
Implementing Hotkeys in React
Let’s dive into how hotkeys can be implemented in a React app, look into possible improvements and go over some popular hotkeys libraries that could be helpful to build hotkeys system for your app.
Adding Hotkeys
This is what the most basic TypeScript hotkey implementation looks like. All hotkeys implementations are based on event listener, attached either to the document object or a specific DOM node.
We can use keydownevent to track keyboard presses by the user. Note that we’ve added a check for the event.repeat
property to neutralise double clicks.
You can always check out all keyboardevents properties on MDN.
export const setupHotkeys = () => {
document.addEventListener("keydown", (event: KeyboardEvent) => {
if (event.repeat) {
return;
}
if (event.ctrlKey && event.key === "l") {
// do what you want to do when CTRL + L is pressed
}
});
};
Hotkeys in a React App
Now let’s implement basic hotkeys as a hook for a React app.
We are using the useLayoutEffect
hook and useRef hooks to recall the most up to date callback to avoid bugs. Here is a very nice article explaining how useLayoutEffect
hook works just in case.
We’re also using the useEffect
callback to attach the listener. Please note that we are removing the event listener in a function that gets returned by the useEffect
hook. (Here is the documentation for useEffect
hook). We do this to ensure we don’t leave the listener attached when the component is removed from dom - this is needed to avoid memory leaks.
export const useHotkeys = (
key: string,
callback: (event: KeyboardEvent) => void
) => {
const callbackRef = useRef(callback);
useLayoutEffect(() => {
callbackRef.current = callback;
});
useEffect(() => {
const handler = (event: KeyboardEvent) => {
if (event.key === key) {
callbackRef.current(event);
}
};
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, [key]);
};
Let’s now implement support for combos.
We start by adding an additional parameter, like a combination key or a modifier - Alt, Ctrl, Shift, and the meta key (Windows logo key or the Mac command key). To support the combination, we’ll add an additional check in the handler so that the app reacts only when the key is pressed in a combination with a modifier key.
type CombinationKey = "alt" | "ctrl" | "meta" | "shift";
export const useHotkeys = (
key: string,
combinationKey: null | CombinationKey,
callback: (event: KeyboardEvent) => void
) => {
const callbackRef = useRef(callback);
useLayoutEffect(() => {
callbackRef.current = callback;
});
useEffect(() => {
const handler = (event: KeyboardEvent) => {
if (
(!combinationKey || event[`${combinationKey}Key`]) &&
event.key === key
) {
callbackRef.current(event);
}
};
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, [key, combinationKey]);
};
React Libraries for Hotkeys
There are lots of hotkey development libraries for React apps, one of the most popular ones being react-hotkeys-hook
.
An example of how hotkey implementation works in this library:
import { useHotkeys } from 'react-hotkeys-hook'
export const Component = () => {
useHotkeys('ctrl+j', () => {/* do something */});
return (
/* some jsx */
)
}
Here’s some other hotkey libraries to check out:
- https://github.com/jaywcjlove/react-hotkeys
- https://gitlab.com/iamnautilusjungle/mousetrap-react
- Hotkey functionality can also be implemented using other libraries, such as Blueprint.js: https://blueprintjs.com/docs/#core/hooks/use-hotkeys
Conclusion
We looked at some ways of building and implementing hotkey systems in React apps. When developing hotkeys, our priority should always be usability and comfort. Well-designed hotkeys can save tons of time for your users and make them happy so it's worth considering hotkeys in your app.
If you found this interesting and want to know more, here are some cool articles on this topic that I've used while researching:
Top comments (0)