JSFiddle - React, Tailwind, and code Playground

by Dmitry Ieremenko

HTML

<div class="cube">
  
</div>

CSS

.cube {
  padding: 1px;
  border: 1px solid  #48AAE6;
  display: inline-block;
  margin: 100px;
  position: relative;
  -webkit-box-sizing: border-box;
  box-sizing: border-box; 
}
.cube__item {
  width: 70px;
  height: 70px;
  background-color: #48AAE6;
  margin: 1px;
  -webkit-box-sizing: content-box;
  box-sizing: content-box; 
}
.cube__row {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  position: relative; 
}
.cube__add {
  background-color: #F3A500;
  width: 70px;
  height: 70px;
  border: 1px solid #fff;
  position: absolute;
  color: #fff;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  cursor: pointer;
  -webkit-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
  transition: all 0.3s ease; 
}
.cube__add:hover {
  background-color: #F6C052;
  -webkit-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
  transition: all 0.3s ease; 
}
.cube__add span {
  margin: auto;
  font-size: 22px;
  font-weight: bold; 
}
.cube__add-item {
  right: -72px; 
}
.cube__add-row {
  bottom: -72px; 
}
.cube__remove {
  background-color: #B20000;
  width: 70px;
  height: 70px;
  position: absolute;
  color: #fff;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  border: 1px solid transparent;
  display: none;
  -webkit-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
  transition: all 0.3s ease;
  font-size: 22px;
  font-weight: bold; 
}
.cube__remove:hover {
  background-color: #CA4C49;
  cursor: pointer; 
}
.cube__remove span {
  margin: auto;
  font-size: 22px;
  font-weight: bold; 
}
.cube__remove-item {
  top: -75px; 
}
.cube__remove-item.active {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex; 
}
.cube__remove-row {
  left: -75px; 
}
.cube__remove-row.active {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex; 
}

JavaScript

class MyCube{
	constructor(wrapper , countRows , countCols){
		this.createCube(wrapper,countRows,countCols);

	}
	createCube(wrapper ,countRows, countCols){ 	// Отрисовываем куб
    /* const self = this */;
    let timeout;
		this.wrapper = document.querySelector(wrapper);
		this.btnRemoveRows = this.createElement('div',['cube__remove','cube__remove-row'] ,"<span>-</span>" , this.wrapper );
		this.btnRemoveCols = this.createElement('div',['cube__remove', 'cube__remove-item'] ,"<span>-</span>" , this.wrapper );
		this.btnAddCols = this.createElement('div',['cube__add', 'cube__add-item'] ,"<span>+</span>",this.wrapper);
		this.btnAddRows = this.createElement('div',['cube__add', 'cube__add-row'] ,"<span>+</span>",this.wrapper );
		this.allRows = [];
		this.allCols = [];
		for(let i = 0 ; i < countRows ; i++ ){
			this.allRows.push(this.createElement('div', 'cube__row',null,this.wrapper));
			for(let j = 0; j < countCols ; j++){
				this.allCols.push(this.createElement('div', 'cube__item',null,this.allRows));
			}
		}
		this.marginTopCols = parseInt(getComputedStyle(this.allCols[0],true).marginTop);
		this.paddingWrapper = parseInt(getComputedStyle(this.wrapper,true).paddingLeft);

		this.createAttrInRowsAndCols();
		this.wrapper.addEventListener('mouseover', this.showBtn.bind(this));
		this.wrapper.addEventListener('mouseover', this.setAttrInBtnRemoveColsRow.bind(this));
		this.btnAddRows.addEventListener('click', this.addRow.bind(this , this.createAttrInRowsAndCols.bind(this)));
		this.btnAddCols.addEventListener('click', this.addCol.bind(this));
		this.btnRemoveCols.addEventListener('click', this.removeCols.bind(this));
		this.btnRemoveRows.addEventListener('click', this.removeRows.bind(this));
    /* this.btnRemoveCols.addEventListener('mouseover', function() {
      if (timeout) {
        clearTimeout(timeout);
      }
    });
    this.btnRemoveRows.addEventListener('mouseover', function() {
      if (timeout) {
        clearTimeout(timeout);
      }
    });...