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;
...