UX for Power Users

How to improve UX and productivity of power users using keyboard shortcuts
Sameer Waskar_avatar
Sameer Waskar
Nov 24, 2021 | 6 min read

The keyboard is one of the primary input sources for any software. We use a keyboard for all sorts of interactions with the software via the command keys. Now how can we use the keyboard and think about the application beyond the typical sighted, mouse-based user experience? Keyboard shortcuts! They're a great efficiency feature that allows users to use the application faster for navigation and/or assistive technology. They help in keeping the experience as straightforward as possible for all types of users.

A good UX must help the users to be efficient with their time. Take an example of the Copy feature. There are multiple ways to copy a file, but we all know that the fastest way is to press Ctrl/Cmd + C. That's a keyboard shortcut! It is universal and is more convenient than using the mouse or asking Siri to do it.

In this blog, we will explore how to take the user experience of your system to the next level using keyboard shortcuts without really changing the experience for anyone else.

Why is your UX slow?

Sometimes a user interface can slow down the users. Yes! you read it right. Observe any experienced designer using designing tools and you will observe that they rely heavily on the use of keyboard shortcuts. Furthermore, just count the times you press Alt + Tab on your laptop to switch open applications. This experience is much faster than the mouse-based interaction method. Another reason to use keyboard shortcuts is because of the lesser amount of hand movement required to complete an action.

Shortcuts/Hotkeys Menu

For applications where the workflow is designed to be executed in a specific order, it is extremely important that the users are given the option of shortcuts/hotkeys to make the process fast. For example, completing a form, closing a modal, printing the invoice, etc. I personal recommend using two-letter shortcuts as they have the advantage to be unique as well as quick to type and convey meaning. Try to incorporate a Help menu, or add a page somewhere in your application that lists down all the hotkeys that are supported. This helps the users know about the feature and he/she can refer to it for updates.

Focus Management

When creating keyboard shortcut designs, don’t forget to specify how hotkeys will appear on the user interface. This is particularly important for the user to correlate the keystrokes with the functionality therein giving semantic meaning to the shortcut.

For example, when filling a form, pressing the tab key should move the user to the next input field, thus preserving the meaning. Such as moving to the Last Name field after the First Name.

Adding Keyboard Shortcuts in React

Two-letter shortcuts, which do not require modifier keys, are more likely to be unique and quick to type and convey meaning. Let's create one for your React web application.

import { useCallback, useEffect, useState } from 'react';

/**
 * A custom hook to detect when the user is pressing a specific key or a collection of keys
 *
 * @param {targetKeys} -  The key(s) to watch
 * @param {defaultPrevented} - To prevent the default action that belongs to the event
 *
 * @returns {boolean} - TRUE returns a match.
 */

export const useKeyPress = (targetKeys: string | string[]): boolean => {
 const [keysPressed, setKeyPressed] = useState<string[]>([]),
  [allKeysPressed, setAllKeysPressed] = useState<boolean>(false);

 const downHandler = useCallback((event: KeyboardEvent) => {
  // This avoid handling of the event if the key is pressed down
  if (event.repeat) return;
  setKeyPressed(oldKeys => Array.from(new Set([...oldKeys, event.key])));
 }, []);

 const upHandler = useCallback((event: KeyboardEvent) => {
  setKeyPressed(oldKeys => oldKeys.filter(oldKey => oldKey !== event.key));
 }, []);

 useEffect(() => {
  Array.isArray(targetKeys)
   ? setAllKeysPressed(targetKeys.every((key, index) => keysPressed[index] === key))
   : setAllKeysPressed(keysPressed.includes(targetKeys));
 }, [targetKeys, keysPressed]);

 useEffect(() => {
  window.addEventListener('keydown', downHandler);
  window.addEventListener('keyup', upHandler);
  return () => {
   window.removeEventListener('keydown', downHandler);
   window.removeEventListener('keyup', upHandler);
  };
 }, []);

 return allKeysPressed;
};

In the above hook, we are listening to the keydown and keyup events exposed by the DOM (document), and executing the associated event handler.

Now let's see how we can use the useKeyPress hook to print a happy emoji.

export const App = () => {
 const isShiftCPressed = useKeyPress(['Shift', 'C']);
 return (
  <>
   <Text>Try pressing the following hotkeys:</Text>
   <Text textWeight={isShiftCPressed ? 'Strong' : 'Regular'}>Shift + C</Text>
   <DisplayDiv>{isShiftCPressed && '😊'}</DisplayDiv>
  </>
 );
};

In the above example, the App component will listen to the 'Shift' + 'C' key events, and will show a "😊" when both the keys are pressed at the same time.

Preventing default behavior

Some key combinations already have default behavior assigned to them by the browser. For example, pressing ”space” scrolls down a page, and ”Control+p” prints the page. To prevent this default behaviour, we can use this function to intercept the event before it gets handled and refrains the default handler from being activated.

const useKeyPress = (targetKeys: string | string[], defaultPrevented = false): boolean => {
    if (targetKeys.length === 0) {
        throw new Error(`[Invalid parameter]: 'targetKeys' cannot be empty.`);
    }

    const [keysPressed, setKeyPressed] = useState<string[]>([]),
        [allKeysPressed, setAllKeysPressed] = useState<boolean>(false);

    const downHandler = useCallback(
        (event: KeyboardEvent) => {
            if (event.repeat) return;
            setKeyPressed(oldKeys => Array.from(new Set([...oldKeys, event.key])));
            // prevents default key action if the flag is set to true
            defaultPrevented && event.preventDefault();
        },
        [defaultPrevented]
    );

    const upHandler = useCallback(
        (event: KeyboardEvent) => {
            setKeyPressed(oldKeys => oldKeys.filter(oldKey => oldKey !== event.key));
            defaultPrevented && event.preventDefault();
        },
        [defaultPrevented]
    );

    // same as above
    useEffect(() => { ... }, []);

    return allKeysPressed;
};

We at Medly have implemented keyboard hotkeys in one of our internal apps. Users familiar with the system are blazing fast at getting through tasks on the system. All thanks to the in-app keyboard shortcuts

Conclusion

Even though mice and gestures have become more distinguished ways of interaction in today’s high tech world, keyboard shortcuts should not be ignored when designing our user experiences, particularly for systems where users perform redundant tasks. Include keyboard shortcuts as part of your design and watch your power users become even more powerful.