JSFiddle - React, Tailwind, and code Playground

by Twisty

HTML

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<table>
  <tr class="drag_me">
    <td>drag me</td>
  </tr>
  <tr class="drag_me">
    <td>drag me</td>
  </tr>
  <tr class="drag_me">
    <td>drag me</td>
  </tr>
  <tr class="drag_me">
    <td>drag me</td>
  </tr>
</table>

<div class="upper"></div>
<div class="drop_area">
  <ul>
    <li class="drop_on_me">drop here 1</li>
    <li class="drop_on_me">drop here 2</li>
    <li class="drop_on_me">drop here 3</li>
    <li class="drop_on_me">drop here 4</li>
    <li class="drop_on_me">drop here 5</li>
    <li class="drop_on_me">drop here 6</li>
    <li class="drop_on_me">drop here 7</li>
    <li class="drop_on_me">drop here 8</li>
    <li class="drop_on_me">drop here 9 </li>
    <li class="drop_on_me">drop here 10</li>
  </ul>
</div>
<div class="lower"></div>

CSS

.drop_area {
  height: auto;
  max-height: 100px;
  overflow-y: scroll;
  border: 1px solid black;
  position: relative;
}

.hover {
  background-color: #CCC;
}

.upper,
.lower {
  height: 16px;
  position: fixed;
  width: 100%;
  background: rgba(50, 50, 50, .5);
  z-index: 10;
}

.lower {
  margin-top: -16px;
}

.active {
  border: 1px solid yellow;
}

JavaScript

$(function() {
  $('.drag_me').draggable({
    helper: 'clone',
    scroll: 'true',
    refreshPositions: true
  });
  $('.drop_on_me').droppable({
    accept: '.drag_me',
    activeClass: 'active',
    hoverClass: 'hover',
    tolerance: 'pointer',
    over: function(e, ui) {
      var buffer = 16;
      var step = 30;
      var speed = 250;
      var upper = $('.drop_area').position().top + buffer;
      var lower = $('.drop_area').position().top + $('.drop_area').height() - buffer;
      var current = $('.drop_area').scrollTop();
      switch (true) {
        case (ui.position.top <= upper):
          console.log("Direction: Up");
          $('.drop_area').animate({
            scrollTop: current - step
          }, speed);
          break;
        case ((ui.position.top + ui.helper.height()) >= lower):
          console.log("Direction: Down");
          $('.drop_area').animate({
            scrollTop: current + step
          }, speed);
          break;
      }
    }
  });
  /*
  $('.upper').droppable({
    over: function(event, ui) {
      $('.drop_area').autoscroll({
        direction: 'up',
        step: 150,
        scroll: true
      });
    },
    out: function(event, ui) {
      $('.drop_area').autoscroll('destroy');
    }
  });

  $('.lower').droppable({
    over: function(event, ui) {
      $('.drop_area').autoscroll({
        direction: 'down',
        step: 150,
        scroll: true
      });
    },
    out: function(event, ui) {
      $('.drop_area').autoscroll('destroy');
    }
  });
  */
});