JSFiddle - React, Tailwind, and code Playground

by fxi

HTML

<div class='page' id='main'>

<form class='form-container'>
<div class='form-group'>
<label class='form-label' for='field-name'>Enter your name</label> 
<div class='form-item' id='field-name'></div>
<p>Hello, my name is... <span id='result'></span></p>
</div>

</form>
<div class='footer'>Made with ♡ for r/badUIbattles</div>
</div>

SCSS

html,body {
  width:100%;
  height:100%;
  overflow:visible;
  display:flex;
  justify-content:center;
  align-items:center;
  background-color: azure;
}

.page {
  width:500px;
height:90%;
  background-color: white;
    border-radius: 20px;
    position:relative;
    .footer {
      position:absulute;
      bottom:0;
      padding:5px;
      color: #ccc;
    }
}


.form-container {
  width:100%;
  height:calc(100% - 40px);
  display:flex;
flex-wrap:wrap;
  position:relative;
  align-items:end;
  justify-content:center;
  .form-group {
    width:80%;
  
     display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  .form-label {
    width:100%;
    
  }
  .form-item {
    width:100%;
    heigth:40px;
    padding:20px;
    border-radius:20px;
    border: 1px solid #000;
    position:relative;

    .kb-stroke {
  position:absolute;
  cursor:pointer;
  transition:transform 1000ms ease-out;
  
}
}
  
  }
  
}

.kb-container {
  width: 360px;
  display: flex;
  border: 1px solid #000;
  border-radius: 20px;
  padding: 20px;
  flex-wrap:wrap;
  resize:both;
  position:absolute;
  top:20%;
  left:20px;
  transition:transform 500ms ease-in-out;
  transform-origin:center;
   background-color: white;
  .kb-key {
    position:relative;
    width: 30px;
    height: 30px;
    border: 1px solid #000;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin:2px;
    cursor:pointer;
    transition:transform 500ms ease-out;
     background-color: white;
    &:before {
      content: attr(data-key);
       pointer-events:none;
    }
    &:not([data-ctrl=true]):hover:after {
      content :'';
      position:absolute;
      top:80%;
      height:calc(100vh);
      width:30px;
      z-index:0;
      background-color: #ccc;
     
      opacity:0.2;
      transform-origin: top center;
     
      
    }

  }


}

JavaScript

const elFn = document.getElementById('field-name');
const elRes = document.getElementById('result');
const elMain = document.getElementById('main');

class badkb {
  constructor(elInput, elPage) {
    const kb = this;
    kb.elInput = elInput;
    kb.elPage = elPage;
    kb.dy = 0;
    kb.dx = 0;
    kb.dr = 0;
    kb.fx = 0;
    kb.fy = 0;
    kb.elKeys = [];
    kb.elKeysCtrl = [];
    kb.elStrokes = [];
    kb.build();
  }
  build() {
    const kb = this;
    kb.elKb = document.createElement('div');

    kb.elKb.className = "kb-container";
    kb.elKb.addEventListener('click', kb.onClick.bind(kb));
    kb.elInput.addEventListener('click', kb.onInputClick.bind(kb))
    kb.elInput.parentElement.appendChild(kb.elKb);
    kb._keysCtrl = "←↑→↓⟳⟲↩↶⾬⌧".split("");
    kb._keysAlpha = "1234567890qwertyuiopasdfghjklzxcvbnm._-⎵".split("").sort();
    kb._keys = [...kb._keysCtrl, ...kb._keysAlpha];

    for (const k of kb._keys) {
      const elK = document.createElement('div');
      const isCtrl = kb._keysCtrl.includes(k);
      elK.className = 'kb-key';
      elK.dataset.key = k;
      elK.dataset.ctrl = isCtrl;
      if (isCtrl) {
        kb.elKeysCtrl.push(elK);
      } else {
        kb.elKeys.push(elK);
      }


      kb.elKb.appendChild(elK);
    }
  }
  rect(elTarget) {
    elTarget = elTarget || this.elKb;
    return elTarget.getBoundingClientRect();
  }
  
 
  move(dir) {
    const kb = this;
    const s = 1;

    const isVertical = ((Math.abs(kb.dr) / 90) % 2) > 0.5
    switch (dir) {
      case 'up':
        kb.dy -= 1 * s;
        break;
      case 'down':
        kb.dy += 1 * s;
        break;
      case 'left':
        kb.dx -= 1 * s;
        break;
      case 'right':
        kb.dx += 1 * s;
        break;
      case 'rotate-c':

        kb.dr += 45 * s;
        break;
      case 'rotate-a':
        kb.dr -= 45 * s;
        break;
      case 'flip-x':
        if (isVertical) {
          kb.fy += 180 * s;
        } else {
          kb.fx += 180 * s;
     ...