JSFiddle - React, Tailwind, and code Playground

HTML

<div class="group">
    <h1>Group 1</h1>
    
    <ul class="parent">
        <li class="droppable"><span class="draggable">Item 1</span></li>
        <li class="droppable"><span class="draggable">Item 2</span></li>
        <li class="droppable"></li>
    </ul>
</div>

<div class="group">
    <h1>Group 2</h1>
    
    <ul class="parent">
        <li class="droppable"><span class="draggable">Item 3</span></li>
        <li class="droppable"></li>
        <li class="droppable"><span class="draggable">Item 4</span></li>
    </ul>
</div>

CSS

* { margin: 0; padding: 0; }
body { font-family: Helvetica, Arial, sans-serif; }
h1 { font-weight: bold; margin-bottom: 10px; }

.group {
    width: 150px;
    margin: 5px 0 5px 5px;
    float: left;
}

.parent {
    list-style-type: none;
}

.parent li {
    height: 41px;
    margin-bottom: 5px;
    padding: 5px;
    background: #ddd;
}

.parent li.active {
    background: yellow;
}

.parent li.hover {
    background: orange;
}

.parent li.hover span {
    opacity: .5;
}

.parent li span {
    display: block;
    height: 25px;
    line-height: 25px;
    padding: 5px;
    background: #eee;
    border: 3px solid #eee;
    cursor: move;
}

.parent li span.ui-draggable-dragging {
    z-index: 10;
    border-color: red;
}

JavaScript

$(".draggable").draggable({
    revert: "invalid",
    revertDuration: 0,
    start: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    },
    drag: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    }

});

$(".droppable").droppable({
    activeClass: "active",
    hoverClass: "hover",
    
    accept: function (draggable) {
        // The droppable (li element).
        var droppable = $(this);
        
        // The droppable which contains the draggable, i.e., the parent element of the draggable (li element).
        var draggablesDropable = draggable.parent();
        
        // Is the draggable being dragged/sorted to the same group?
        // => We could just sort it, because there's always enough space inside the group.
        if (droppable.parent().is(draggablesDropable.parent())) {
           return true;
        }
        
        // Nope, the draggable is being dragged/sorted to another group.
        // => Is there an empty droppable left in the group to which the draggable is being dragged/sorted?
        else if (droppable.parent().find(".draggable").size() < droppable.parent().find(".droppable").size()) {
            return true;
        }
        
        // Nothing true?
        return false;
    },
    
    drop: function(event, ui) {
        // The droppable (li element).
        var droppable = $(this);
        
        // The draggable (span element).
        var draggable = ui.draggable;
        
        // The droppable which contains the draggable, i.e., the parent element of the draggable (li element).
        var draggablesDropable = draggable.parent();
        
        // Is the draggable being dragged to it's own droppable?
        // => Abort, there's nothing to drag/sort!
        if (droppable.is(draggablesDropable)) {
            return;
        }
        
        // Is the draggable being dragged to an empty droppable?
        else if (!droppable.find(".draggable").size())...