JSFiddle - React, Tailwind, and code Playground

by Plippie Plop

HTML

<div class="container">
  <ul id="list">

  </ul>
</div>

CSS

ul,
li {
  list-style: none;
  padding: 0;
  margin: 0;
}

.container {
  display: flex;
  flex-direction: column;
  height: 50vh;
  border: 1px solid grey;
  overflow: hidden;
  overflow-y: auto;
}

#list {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}

#list li {
  padding: .5em;
  border-bottom: 1px solid grey;
}

li.selected {
  background: grey
}

JavaScript

var ul = document.getElementById('list');
var liSelected;
var index = -1;
var list = "";
for (var x = 0; x < 100; x++) {

  list += '<li tabindex="' + x + '">Item ' + x + '</li>';

}

ul.insertAdjacentHTML('beforeend', list);


document.addEventListener('keydown', function(e) {
  e.stopPropagation();

  var len = ul.getElementsByTagName('li').length - 1;

  if (e.which === 40) {
    e.preventDefault();
    index++;
    //down 
    if (liSelected) {

      removeClass(liSelected, 'selected');
      next = ul.getElementsByTagName('li')[index];

      if (typeof next !== undefined && index <= len) {

        liSelected = next;

      } else {

        index = 0;
        liSelected = ul.getElementsByTagName('li')[0];
      }

      addClass(liSelected, 'selected');
      console.log(index);

    } else {

      index = 0;

      liSelected = ul.getElementsByTagName('li')[0];
      addClass(liSelected, 'selected');
    }
    liSelected.scrollIntoView({behavior:"smooth"});

  } else if (e.which === 38) {
    e.preventDefault();
    //up
    if (liSelected) {
      removeClass(liSelected, 'selected');
      index--;
      console.log(index);
      next = ul.getElementsByTagName('li')[index];
      
      if (typeof next !== undefined && index >= 0) {
        liSelected = next;
      } else {
        index = len;
        liSelected = ul.getElementsByTagName('li')[len];
      }
      
      addClass(liSelected, 'selected');
      
    } else {
    
      index = 0;
      liSelected = ul.getElementsByTagName('li')[len];
      addClass(liSelected, 'selected');
    }
    liSelected.scrollIntoView({behavior:"smooth"});
    
  }
  
}, false);

function removeClass(el, className) {
  if (el.classList) {
    el.classList.remove(className);
  } else {
    el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
  }
};

function addClass(el, className) {

  if (el.classList) {
    el.classList.add(className);
  } else {
  ...