Reputation: 94
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
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
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