Home > Software design >  How to use keyboard events in React to make a widget keyboard?
How to use keyboard events in React to make a widget keyboard?

Time:05-23

This is my code

import React, { useState, useRef } from "react";

const alphabet = ["A", "B", "C", "D", "E"];

export default function App() {
  const [selected, setSelected] = useState<number | null>(null);
  const selectedRef = useRef<HTMLDivElement>(null);

  const selectLetter = (i: number) => {
    if (selected === i) {
      setSelected(null);
    } else {
      setSelected(i);
    }
  };

  const navigate = (
    event: React.KeyboardEvent<HTMLDivElement>,
    letter: string,
    i: number
  ) => {
    if (event.key === "Enter") {
      if (i === selected) {
        setSelected(null);
      } else {
        setSelected(i);
      }
    }
  };

  return (
    <div
      tabIndex={-1}
      style={{
        display: "flex",
        gap: "5px",
        flexWrap: "wrap"
      }}
    >
      {alphabet.map((letter: string, i: number) => (
        <div
          ref={selected === i ? selectedRef : null}
          onClick={() => selectLetter(i)}
          onKeyDown={(event) => navigate(event, letter, i)}
          tabIndex={selected === i ? 0 : -1}
          style={{
            border: "1px solid blue",
            padding: "30px",
            backgroundColor: i === selected ? "blue" : "white",
            color: i === selected ? "white" : "black",
            fontWeight: "bolder",
            cursor: "pointer"
          }}
        >
          {letter}
        </div>
      ))}
    </div>
  );
}

I have the letters "A", "B", "C", "D", "E". If I click them, then they get highlighted. Only one letter can be selected at a time and it could be deselected if you click them again. That part works fine.

The part I'm having trouble with is integrating keyboard to work too.

I also want to be able to use my keyboard and do the same thing but instead with keyboard. Like lets say by default the tabIndex is on "A". if I press enter it would highlight "A"

enter image description here

If I press enter again (deselects 'A')

enter image description here

I should also be able to use arrow key to move the tabIndex, so for example if I use the right key then it would be focused on "B". And then when I press enter, then B should be highlighted

enter image description here

I should freely be able to navigate A,B,C,D,E with my keyboard.

I'm reading the tabindex article in mozilla and I just cant figure it out. I somewhat have the enter working but after one press I'm unsure how to get the tabindex to move.

myplayground: https://codesandbox.io/s/clever-aryabhata-vxoi90?file=/src/App.tsx:0-1358

CodePudding user response:

First, you want your tabIndex be 0 for all elements so you can navigate through them in sequential order with the Tab key. That's the only purpose of the tabIndex attribute here.

Then, for navigating through arrow keys you can check for the ArrowLeft / ArrowRight event.key, and then .focus() the previous / next element:

if (event.key === "ArrowLeft") {
  document.querySelectorAll("#root div div")[i-1]?.focus();
}
if (event.key === "ArrowRight") {
  document.querySelectorAll("#root div div")[i 1]?.focus();
}

Here's your updated codesandbox: https://codesandbox.io/s/empty-tdd-8g3prn?file=/src/App.tsx

  • Related