Easily see the JavaScript Keyboard Event KeyCodes with keycode.info

Handy helper tool by Wes Bos: simply press any key and see the results for KeyboardEvent.which, KeyboardEvent.key,KeyboardEvent.code, etc.

As a user with an AZERTY keyboard layout I often have a broken experience on sites that respond to first row of keys, e.g. QWERTY. As those sites respond to KeyboardEvent.key — which differs from layout to layout — I cannot simply use the first row, but have to reach for the Q and W keys on the second and third row.

To properly implement key presses independent of the keyboard layout, it’s recommended to use e.keyCode as that will yield the same keyCode. As per MDN:

The KeyboardEvent.code property represents a physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value that isn’t altered by keyboard layout or the state of the modifier keys.

For example: pressing A on AZERTY will yield KeyQ. Pressing Q on QWERTY will also yield KeyQ as they’re the same physical key.

JavaScript Event KeyCodes →

:focus-visible Is Here

With Chromium 86 and now recently Firefox 85 supporting :focus-visible, it’s a good time to refer to this post by Matthias Ott:

The :focus-visible pseudo-class lets you show focus styles only when they are needed, using the same heuristic that the browser uses to decide whether to show the default focus indicator.

You use :focus-visible just like you use :focus. To properly hide focus rings on “mouse focus” though, you’ll need to add an extra rule-set in which you combine :focus with (a negated) :focus-visible:

/* Show focus styles on keyboard focus. */
:focus-visible {
  outline: 3px solid blue;
}

/* Hide focus styles if they're not needed, for example, 
when an element receives focus via the mouse. */
:focus:not(:focus-visible) {
  outline: 0;
}

💁‍♂️ This extra rule-set is needed because browser vendors add a default outline using :focus through their User Agent StyleSheet.

In the (near?) future this extra rule-set will no longer be needed as the HTML spec now prescribes that UA StyleSheets use :focus-visible to add the default outline.

Awaiting the work Igalia is doing on this, Safari does not yet support :focus-visible, but in the meantime you can use a polyfill.

:focus-visible Is Here →
focus-visible Polyfill →

How Discord Implemented App-Wide Keyboard Navigation

When working on creating a complete keyboard navigation experience for Discord, using styling with :focus and outline, the folks at Discord ran into issues where the outline would not match the shape of actual element being rendered. Thinks like border-radius, overflow: hidden; on the container, padding got in the way. So they set out to find a solution.

After a lot of trial and error, we landed on a system which is built on two components: FocusRing for declaring where a ring should be placed, and FocusRingScope for declaring a root position for rings to be rendered.

Here’s an example showing how the FocusRing works:

function SearchBar() {
  const containerRef = React.useRef<HTMLDivElement>(null);
  const inputRef = React.useRef<HTMLInputElement>(null);
  return (
    <FocusRing focusTarget={inputRef} ringTarget={containerRef}>
      <div className={styles.container} ref={containerRef}>
        <input type="text" ref={inputRef} placeholder="Search" />
        <div className={styles.icon}>
          <ClearIcon />
        </div>
      </div>
    </FocusRing>
  );
}

The FocusRing will capture focussing of the contained input, but will render the ring around the entire div. To have a FocusRing behave like :focus-within and respond to any descendant being focussed, you can set the within prop.

The package can be installed using NPM:

npm i react-focus-rings

How Discord Implemented App-Wide Keyboard Navigation →
Browser Focus Ring Problems →
react-focus-rings (GitHub) →

Related: Not entirely coincidental the aforementioned React Spectrum by Adobe also comes with a FocusRing component.

tinykeys – A tiny and modern library for keybindings

Small and lightweight, I like:

import tinykeys from "tinykeys"

tinykeys(window, {
  "Shift+D": () => {
    alert("The 'Shift' and 'd' keys were pressed at the same time")
  },
  "y e e t": () => {
    alert("The keys 'y', 'e', 'e', and 't' were pressed in order")
  },
  "$mod+KeyD": () => {
    alert("Either 'Control+d' or 'Meta+d' were pressed")
  },
});

When calling tinykeys it returns an unsubscribe function. Handy when developing components:

import { useEffect } from "react"
import tinykeys from "tinykeys"

function useKeyboardShortcuts() {
  useEffect(() => {
    let unsubscribe = tinykeys(window, {
      // ...
    });
    return () => {
      unsubscribe(); // make use of the returned unsubscribe() function.
    }
  })
}

Installation per NPM/Yarn

npm install tinykeys

tinykeys →
tinykeys Source (GitHub) →

Prevent Apple’s “double key press” on the butterfly keyboard with Unshaky

If you’re having this “double key press” issue, Unshaky is a software solution that will help you get by.

Unshaky tries to address an issue on the butterfly keyboard (Macbook, Macbook Air 2018 & MacBook Pro 2016 and later): Double Key Press. Unshaky might save your keyboard by dismissing such “second key hits” (any key presses that occur no later than x milliseconds after the previous effective one).

Installable through Brew Cask, or per direct download from the site:

brew cask install unshaky

Won’t fix the fact that the keyboard doesn’t sit well on the fingers …

Unshaky: A software attempt to address the “double key press” issue on Apple’s butterfly keyboard →

🚨 As Apple has acknowledged these issues, don’t forget to apply for Apple’s Keyboard Service Program for MacBook and MacBook Pro to get a new keyboard, free of charge.

NYSKeyboardHelper – A helper for all your iOS keyboard needs

Matthias Nys, a former student of mine, has released his first pod NYSKeyboardHelper, a helper which resizes a scrollview so that it doesn’t go under the keyboard.

Add a constraint to your project’s Storyboard and set NYSKeyboardHelper as the custom class, or add it programmatically:

let keyboardConstraint = NYSKeyboardHelper(item: self.view, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1.0, constant: 0.0)
keyboardConstraint.extraIndent = 10.0
self.view.addConstraint(keyboardConstraint)

NYSKeyboardHelper – A Helper for all your keyboard needs →

In React Native, use the KeyboardAvoidingView to make sure the keyboard doesn’t overlap with the content 😉

Keystroke Recognition Using WiFi Signals

WiKey

We’re all doomed:

In this paper, we propose a WiFi signal based keystroke recognition system called WiKey. WiKey consists of two Commercial Off-The-Shelf (COTS) WiFi devices, a sender (such as a router) and a receiver (such as a laptop). The sender continuously emits signals and the receiver continuously receives signals. When a human subject types on a keyboard, WiKey recognizes the typed keys based on how the CSI values at the WiFi signal receiver end.

Obviously that must not be accurate at all, right? Erm, wrong:

WiKey achieves more than 97.5% detection rate for detecting the keystroke and 96.4% recognition accuracy for classifying single keys. In real-world experiments, WiKey can recognize keystrokes in a continuously typed sentence with an accuracy of 93.5%.

Keystroke Recognition Using WiFi Signals (Paper) →