Roman's answer is helpful. I took this a step further by creating functions that handle moving focus up or down.
In the component I have my handleKeyDown function called on the onKeyDown event:
<UnorderedList id='unordered-list' onKeyDown={handleKeyDown} />
To call the functions I used an if statement like this below in my onKeyDown handler:
const handleKeyDown = (e) => {
if(e.key === 'ArrowDown') {
moveFocusDown()
}
if(e.key === 'ArrowUp') {
moveFocusUp()
}
}
Next for the moveFocusDown function, I did the following:
const moveFocusDown = () => {
const listItems = document.querySelector('#unordered-list').childNodes
const activeItem = document.activeElement
for(let i = 0; i < listItems.length; i++) {
const listLength = listItems.length
if(activeItem === listItems[i] && activeItem !== listItems[listLength - 1]) {
listItems[i + 1].focus()
}
}
}
The conditional activeItem === listItems[i] && activeItem !== listItems[listLength - 1]
checks that the activeItem and the current index of the Unordered List child nodes are the same, then checks that the last element in the node list isn't the active element. This is needed to prevent moving focus to an element that doesn't exist.
The moveFocus up function is a little simpler:
const moveFocusUp = () => {
const listItems = document.querySelector('#menu').childNodes
const activeItem = document.activeElement
for(let i = 0; i < listItems.length; i++) {
if(activeItem === listItems[i] && activeItem !== listItems[0]) {
listItems[i - 1].focus()
}
}
}