JSFiddle - React, Tailwind, and code Playground

Editor Layout Experiments

by nilloc

HTML

<container id="editor">
  <container id="toolbar">
    toolbar
  </container>
  <container id="drawer">
    drawer
  </container>
  <container id="handle"></container>
  <container id="stage" 
    data-top="toolbar" 
    data-left="handle"
    data-right="0"
    data-bottom="0">
    stage
    <anchor class="top" contenteditable data-setting="toolbar">toolbar</anchor>
    <anchor class="left" contenteditable data-setting="handle">handle</anchor>
    <anchor class="right" contenteditable data-setting="right">0</anchor>
    <anchor class="bottom" contenteditable data-setting="bottom">0</anchor>
  </container>
</container>

SCSS

*{
  box-sizing:border-box;
}
container{
  display:block;
  position:relative;
  user-select:none;
}

#editor, #drawer, #handle, #stage{
  position:absolute;
}

#editor{
  background:darkgray;
  top:0;
  left:0;
  bottom:0;
  right:0;
  
  $toolbar-height:60px;
  $drawer-width:200px;
  $handle-width:4px;
  
  #toolbar{
    background:lightgray;
    height:$toolbar-height;
    padding:10px;
  }
  #drawer{
    background:white;
    top:$toolbar-height;
    left:0;
    width:$drawer-width;
    bottom:0;
  }
  #handle{
    background:#777;
    top:$toolbar-height;
    left:$drawer-width;
    width:$handle-width;
    bottom:0;
    cursor:col-resize;
    z-index:1000;
  }
  #stage{
    background:#eee;
    top:$toolbar-height;
    left:$drawer-width+$handle-width;
    right:0;
    bottom:0;
  }
  
  
  anchor{
    display:block;
    position:absolute;
    height:20px;
    width:60px;
    background:white;
    border:1px solid darkgray;
    border-radius:4px;
    text-align:center;
    outline: none;
    overflow:hidden;
    
    &.top,  &.bottom{left:calc(50% - 30px);}
    &.left, &.right{top:calc(50% - 30px);}
    &.top, &.left, &.right{border-radius:0 0 4px 4px;}
    &.top{top:0;}
    &.bottom{bottom:0;  border-radius:4px 4px 0 0;}
    &.left{   left:-20px; transform:rotate(-90deg); }
    &.right{ right:-20px; transform:rotate(90deg);  }
  }

}

JavaScript

$('anchor').on("input", function(){
	console.log($(this).parent(), "changed:", this.textContent);
  var $parent = $(this).parent();
  if(this.textContent.indexOf('%') > -1){
    $parent.css(this.className, this.textContent); // make %
    this.dataset.setting = this.textContent;
  }else if(this.textContent == parseFloat(this.textContent)){
  	$parent.css(this.className, this.textContent+"px"); // make abs
    this.dataset.setting = this.textContent;
  }else{
  	// search for id and attach based on edge
    var $target = $('container#'+this.textContent);
    if($target.length > 0 ){
    	console.log("found:", $target);
      this.dataset.setting = this.textContent;
      switch(this.className){
      	case 'top':
        console.log($target.offset().top+$target.outerHeight());
        $parent.css('top', $target.offset().top+$target.outerHeight()+"px");
        break;
        case 'left':
        $parent.css('left', $target.offset().left+$target.outerWidth()+"px");
        break;
        case 'right':
        $parent.css('right', $target.offset().left+"px");
        break;
				case 'bottom':
        $parent.css('top', $target.offset().top+"px");
        break;
      }
    }
  }
});

$('#handle').on('mousedown', function(){
	$('#editor').on('mousemove.handle', function(evt){
  	//console.log("dragging mouse", evt.pageX);
    var handlePos = evt.pageX+'px';
    $('#handle').css('left', handlePos);
    $('#drawer').css('width', handlePos);
		$("anchor[data-setting='handle']").trigger('input');
  });
}).on('mouseup', function(){
	$('#editor').off('mousemove.handle');
});