JSFiddle - React, Tailwind, and code Playground

by Ben Schnell

HTML

<ul class="container" data-alignment="horizontal">
    <li class="draggable" draggable="true"><span>0</span> Colorado</li>
    <li class="draggable" draggable="true"><span>1</span> Montana</li>
    <li class="draggable" draggable="true"><span>2</span> Utah</li>
    <li class="draggable" draggable="true"><span>3</span> Montana</li>
    <li class="draggable" draggable="true"><span>4</span> Wyoming</li>
  </ul>

  <ul class="container">
    <li class="draggable" draggable="true"><span>0</span> Maine</li>
    <li class="draggable" draggable="true"><span>1</span> North Carolina</li>
    <li class="draggable" draggable="true"><span>2</span> Florida</li>
    <li class="draggable" draggable="true"><span>3</span> Virginia</li>
    <li class="draggable" draggable="true"><span>4</span> New York</li>
  </ul>

CSS

.container {
  max-width: 300px;
  display: flex;
  flex-wrap: wrap;
}
.container li {
  height: 30px;
  background-color: #fafafa;
  border: 1px solid #888;
  display: flex;
  align-items: center;
}
.dragging {
  opacity: 0.5;
}

.container li span {
  background-color: #000;
  margin-right: 10px;
  color: #fff;
  padding: 0 10px;
  height: 100%;
  display: flex;
  align-items: center;
}

JavaScript

const draggables = document.querySelectorAll('.draggable')
const containers = document.querySelectorAll('.container')

draggables.forEach(draggable => {
  draggable.addEventListener('dragstart', () => {
    draggable.classList.add('dragging')
  })

  draggable.addEventListener('dragend', (e) => {
    draggable.classList.remove('dragging');
    dragUpdateNr();
  })
})

containers.forEach(container => {
	container.addEventListener('dragover', dragOver);
})

function dragOver(e) {
	 e.preventDefault()
    const afterElement = getDragAfterElement(this, e);
    const draggable = document.querySelector('.dragging')
    if (afterElement == null) {
      this.appendChild(draggable)
    } else {
      this.insertBefore(draggable, afterElement)
    }
}

function getDragAfterElement(container, event) {
	const dataAlignment = container.getAttribute('data-alignment');
  const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')];
  
  return draggableElements.find((draggableElement) => {
  	const box = draggableElement.getBoundingClientRect();
    const x = event.clientX;
    const y = event.clientY;
    const boxLeftSideBounds = [box.x, ]
    if () {
    	return true;
    } else {
    	return false;
    }
    console.log(box, x, y);
  });

/*   return draggableElements.reduce((closest, child) => {
    const box = child.getBoundingClientRect()
    const offset = (dataAlignment === 'horizontal') ?
      event.clientX - box.right - box.width / 2 :
      event.clientY - box.top - box.height / 2;
    if (offset < 0 && offset > closest.offset) {
      return { offset: offset, element: child }
    } else {
      return closest
    }
  }, { offset: Number.NEGATIVE_INFINITY }).element */
}

function dragUpdateNr() {
    let uls = document.querySelectorAll('ul.container');
    
    uls.forEach(ul => {
        let lis = ul.querySelectorAll('li.draggable');
        for (let i=0; i<lis.length; i++) {
            let li = lis[i];
           ...