JSFiddle - React, Tailwind, and code Playground

by William Green

HTML

<div id="projectContainer">
  <div id="dragSourceContainer">
    <div id="squareSource"></div>
  </div>
  <div id="workspaceContainer">
    <div id="workspace"></div>
  </div>
</div>

CSS

html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}

#projectContainer {
  width: 100%;
  height: 100%;
  background-color: #eee;
}

* {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -o-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -ms-box-sizing: border-box;
  box-sizing: border-box;
}

#dragSourceContainer {
  width: 25%;
  height: 100%;
  background: #ddd;
  float: left;
}

#squareSource {
  width: 20vw;
  height: 20vw;
  margin: auto;
  top: 50%;
  position: relative;
  -o-transform: translate(0%, -50%);
  -moz-transform: translate(0%, -50%);
  -webkit-transform: translate(0%, -50%);
  -ms-transform: translate(0%, -50%);
  transform: translate(0%, -50%);
  background-color: #333;
  -o-transition: border .3s ease;
  -moz-transition: border .3s ease;
  -webkit-transition: border .3s ease;
  -ms-transition: border .3s ease;
  transition: border .3s ease;
}

.square:active {
  opacity: .7;
}

.square {
  position: absolute;
  width: 20vw;
  height: 20vw;
  background-color: #333;
  -o-transition: border .5s ease;
  -moz-transition: border .5s ease;
  -webkit-transition: border .5s ease;
  -ms-transition: border .5s ease;
  transition: border .5s ease;
  border: 3px solid transparent;
}

#workspaceContainer {
  float: right;
  background-color: #eee;
  width: 75%;
  height: 100%;
  overflow: auto;
}

#workspace {
  height: 200%;
  width: 100%;
  overflow: hidden;
}

[data-long-transition] {
  -o-transition: all .3s ease;
  -moz-transition: all .3s ease;
  -webkit-transition: all .3s ease;
  -ms-transition: all .3s ease;
  transition: all .3s ease;
}

JavaScript

window.addEventListener('load', function() {
  var status = {
    mouseDown: false,
    activeElement: false,
    activeDragElem: false,
    activeClickPos: {
      x: 0,
      y: 0
    }
  };

  var squareSourcePos = {
    x: 0,
    y: 0
  };

  resetSquareSourcePos();

  squareSource = document.getElementById('squareSource')

  window.addEventListener('mousemove', function(e) {
    if (status.mouseDown == true) {
      if (status.activeElement) {
        //user is dragging the square
        if (status.activeDragElem) {
          //a new element has already been created
          status.activeDragElem.style.top = e.pageY - status.activeClickPos.y + 'px';
          status.activeDragElem.style.left = e.pageX - status.activeClickPos.x + 'px';
        } else {
          //create a new element for shadowing and for workspace
          var newSquare = document.createElement('div');
          newSquare.className = 'square';
          newSquare.style.top = e.pageY - status.activeClickPos.y + 'px';
          newSquare.style.left = e.pageX - status.activeClickPos.x + 'px';
          document.body.appendChild(newSquare)
          status.activeDragElem = newSquare;
        }
      }
    }
  });

  window.addEventListener('mousedown', function(e) {
    status.mouseDown = true;
    if (e.target == squareSource) {
      //moused down on the square drag source
      e.target.style.opacity = '.7';
      e.target.style.border = '3px dashed #FF4357';
      status.activeElement = e.target;
      status.activeClickPos.x = e.offsetX;
      status.activeClickPos.y = e.offsetY;
    }
  });

  window.addEventListener('mouseup', function(e) {
    status.mouseDown = false;
    if (status.activeElement) {
      status.activeElement.style.opacity = '1';
      status.activeElement.style.border = '3px dotted transparent';
      status.activeDragElem.style.display = 'none';
      var elem = document.elementFromPoint(e.pageX, e.pageY);
      if (elem.className == 'square') {
        //dragged...