JSFiddle - React, Tailwind, and code Playground

by RubaXa

HTML

<ul id="list">
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    <li>item 4</li>
    <li>item 5</li>
</ul>

CSS

ul {
    margin: 0;
    padding: 0;
    list-style: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

li {
    cursor: move;
    margin: 1px;
    padding: 5px 20px;
    font-size: 20px;
    background-color: #ccc;
}

.ghost {
    opacity: .4;
}
}

JavaScript

function sortable(rootEl, onUpdate){
    var dragEl;
    [].slice.call(rootEl.children).forEach(function (itemEl){ itemEl.draggable = true; });
    function _onDragOver(evt){
        evt.preventDefault();
        evt.dataTransfer.dropEffect = 'move';
        if( evt.target && evt.target !== dragEl && evt.target.nodeName == 'LI' )
            rootEl.insertBefore(dragEl, evt.target.nextSibling || evt.target);
    }
    function _onDragEnd(evt){
        evt.preventDefault();
        dragEl.classList.remove('ghost');
        rootEl.removeEventListener('dragover', _onDragOver, false);
        rootEl.removeEventListener('dragend', _onDragEnd, false);
        onUpdate(dragEl);
    }
    rootEl.addEventListener('dragstart', function (evt){
        dragEl = evt.target;
        evt.dataTransfer.effectAllowed = 'move';
        evt.dataTransfer.setData('Text', dragEl.textContent);
        rootEl.addEventListener('dragover', _onDragOver, false);
        rootEl.addEventListener('dragend', _onDragEnd, false);
        setTimeout(function (){ dragEl.classList.add('ghost'); }, 0);
    }, false);
}
                        
// Используем                    
sortable( document.getElementById('list'), function (item){
    console.log(item);
});