Gunal Bondre
Gunal Bondre

Reputation: 94

how to make dropdown work using up and down arrow keys in react

i am trying to make a custom dropdown using react where it should work with keyboard up and down keys also

this is what i tried so far

import React, { useState, useEffect, useRef } from "react";
import "./dropdown.scss";

const Dropdown = ({ selected, setSelected }) => {
  const [open, setOpen] = useState(false);
  const options = ["Option1", "Option2", "Option3", "Option4"];
  const [cursor, setCurser] = useState(0);

  //   const label = ["frontend", "backend"];

  let menuRef = useRef();
  // let menuRef1 = useRef();

  useEffect(() => {
    let handler = (e) => {
      if (!menuRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener("mousedown", handler);
    return () => {
      document.removeEventListener("mousedown", handler);
    };
  });

 

  const handleKeyDown = (e) => {
    if (e.keyCode === 38 && cursor > 0) {
      setCurser({
        ...cursor,
        cursor: cursor + 1,
      });
      console.log(cursor);
    } else if (e.keyCode === 40 && cursor < options.length - 1) {
      setCurser({
        ...cursor,
        cursor: cursor - 1,
      });
    }
  };
  return (
    <div>
      <div className="dropdown">
        <div
          ref={menuRef}
          onKeyPress={handleKeyDown}
          className={
            open ? "dropdown-wrapper--up dropdown-wrapper " : "dropdown-wrapper"
          }
        >
          <div className="dropdown-container">
            <div
              className={"dropdown-header"}
              onClick={() => setOpen(!open)}
              // ref={menuRef1}
            >
              {!open ? (
                <div className={selected ? "title-active " : "dropdown-title"}>
                  {selected ? selected : "dropdown-select"}
                </div>
              ) : (
                <div className={selected ? "active-color " : "dropdown-title"}>
                  {selected ? selected : "dropdown-select"}
                </div>
              )}
              <i
                className={open ? "fas fa-chevron-up" : "fas fa-chevron-down"}
              ></i>
            </div>
            {open ? (
              <div
                className={selected ? "active-label active-label--up" : "label"}
              >
                {open ? "Hint Text" : "Title"}{" "}
              </div>
            ) : (
              <div className={selected ? "active-label " : "label "}>
                {open ? "Hint Text" : "Title"}{" "}
              </div>
            )}
          </div>
          {open && (
            <ul className="list">
              {options.map((option, i) => (
                <li
                  onClick={() => {
                    setSelected(option);
                    setOpen(false);
                  }}
                  className="list-item"
                  tabIndex="0"
                >
                  {option}
                </li>
              ))}
            </ul>
          )}
        </div>
      </div>
    </div>
  );
};

export default Dropdown;

here is the output

enter image description here

i want to move between options using up and down arrow key... tried many solutions but not working

i am using array as option list and mapping through it and displaying in dropdown. everything is working fine but just dont know how to map keyboard keys to option list

Upvotes: 2

Views: 3408

Answers (1)

Judith Hartmann
Judith Hartmann

Reputation: 381

You can create an Array of refs for each option

const optionRefs = useRef(options.map(() => createRef()));

then use the these refs

options.map((option, index) => (<li ... ref={optionRefs.current[index]} >...</li>)

and then change the focus to the ref when you navigate... like focussing the first on down arrow:

optionRefs.current[0].current?.focus();

Upvotes: 4

Related Questions