<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clavier One — Virtual Keyboard</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
background:
radial-gradient(circle at 20% 20%, #172554 0, transparent 35%),
radial-gradient(circle at 80% 80%, #312e81 0, transparent 35%),
#050816;
color: #fff;
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
padding: 25px;
}
.wrapper {
width: min(1100px, 100%);
}
.header {
text-align: center;
margin-bottom: 22px;
}
.logo {
font-size: 34px;
font-weight: 800;
letter-spacing: 2px;
}
.logo span {
color: #7c3aed;
}
.subtitle {
color: #94a3b8;
margin-top: 7px;
}
.panel {
background: rgba(15, 23, 42, .82);
border: 1px solid rgba(148, 163, 184, .15);
border-radius: 24px;
padding: 22px;
box-shadow: 0 25px 80px rgba(0,0,0,.45);
backdrop-filter: blur(18px);
}
textarea {
width: 100%;
height: 115px;
resize: vertical;
border: 1px solid rgba(148,163,184,.18);
outline: none;
border-radius: 16px;
padding: 18px;
background: #020617;
color: #f8fafc;
font-size: 19px;
line-height: 1.5;
margin-bottom: 22px;
}
textarea:focus {
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124,58,237,.15);
}
.keyboard {
background: #020617;
border-radius: 20px;
padding: 16px;
overflow-x: auto;
}
.row {
display: flex;
gap: 7px;
margin-bottom: 7px;
min-width: 780px;
}
.key {
height: 55px;
min-width: 55px;
flex: 1;
border: 1px solid #263244;
border-radius: 10px;
background: linear-gradient(145deg, #182235, #0d1525);
color: #e2e8f0;
font-size: 14px;
font-weight: 700;
cursor: pointer;
box-shadow:
0 5px 0 #050a13,
0 8px 14px rgba(0,0,0,.3);
transition: .08s ease;
user-select: none;
}
.key:hover {
border-color: #7c3aed;
color: #fff;
box-shadow:
0 5px 0 #050a13,
0 0 18px rgba(124,58,237,.25);
}
.key:active,
.key.active {
transform: translateY(5px);
box-shadow: 0 0 0 #050a13;
background: linear-gradient(145deg, #7c3aed, #4f46e5);
}
.wide {
flex: 1.8;
}
.extra-wide {
flex: 2.7;
}
.space {
flex: 6;
}
.controls {
display: flex;
justify-content: space-between;
gap: 10px;
margin-top: 18px;
flex-wrap: wrap;
}
button.control {
border: 0;
border-radius: 10px;
padding: 11px 17px;
cursor: pointer;
background: #172033;
color: #cbd5e1;
border: 1px solid #263244;
}
button.control:hover {
border-color: #7c3aed;
color: white;
}
.rgb {
display: flex;
align-items: center;
gap: 8px;
color: #94a3b8;
}
.rgb input {
width: 45px;
height: 28px;
border: 0;
background: transparent;
cursor: pointer;
}
.status {
text-align: center;
color: #64748b;
font-size: 13px;
margin-top: 15px;
}
@media (max-width: 700px) {
body {
padding: 12px;
}
.panel {
padding: 12px;
}
.logo {
font-size: 27px;
}
textarea {
height: 100px;
}
.keyboard {
padding: 10px;
}
}
</style>
</head>
<body>
<div class="wrapper">
<div class="header">
<div class="logo">clavier<span>.one</span></div>
<div class="subtitle">Professional Virtual Keyboard</div>
</div>
<div class="panel">
<textarea
id="editor"
placeholder="Start typing here..."
autofocus
></textarea>
<div class="keyboard">
<div class="row">
<button class="key" data-key="Escape">Esc</button>
<button class="key" data-key="F1">F1</button>
<button class="key" data-key="F2">F2</button>
<button class="key" data-key="F3">F3</button>
<button class="key" data-key="F4">F4</button>
<button class="key" data-key="F5">F5</button>
<button class="key" data-key="F6">F6</button>
<button class="key" data-key="F7">F7</button>
<button class="key" data-key="F8">F8</button>
<button class="key" data-key="F9">F9</button>
<button class="key" data-key="F10">F10</button>
<button class="key" data-key="F11">F11</button>
<button class="key" data-key="F12">F12</button>
</div>
<div class="row">
<button class="key" data-value="`">~<br>`</button>
<button class="key" data-value="1">!<br>1</button>
<button class="key" data-value="2">@<br>2</button>
<button class="key" data-value="3">#<br>3</button>
<button class="key" data-value="4">$<br>4</button>
<button class="key" data-value="5">%<br>5</button>
<button class="key" data-value="6">^<br>6</button>
<button class="key" data-value="7">&<br>7</button>
<button class="key" data-value="8">*<br>8</button>
<button class="key" data-value="9">(<br>9</button>
<button class="key" data-value="0">)<br>0</button>
<button class="key" data-value="-">_<br>-</button>
<button class="key" data-value="=">+<br>=</button>
<button class="key wide" data-key="Backspace">Backspace</button>
</div>
<div class="row">
<button class="key wide" data-key="Tab">Tab</button>
<button class="key" data-value="q">Q</button>
<button class="key" data-value="w">W</button>
<button class="key" data-value="e">E</button>
<button class="key" data-value="r">R</button>
<button class="key" data-value="t">T</button>
<button class="key" data-value="y">Y</button>
<button class="key" data-value="u">U</button>
<button class="key" data-value="i">I</button>
<button class="key" data-value="o">O</button>
<button class="key" data-value="p">P</button>
<button class="key" data-value="[">{<br>[</button>
<button class="key" data-value="]">}<br>]</button>
<button class="key" data-value="\">|<br>\</button>
</div>
<div class="row">
<button class="key wide" data-key="CapsLock">Caps Lock</button>
<button class="key" data-value="a">A</button>
<button class="key" data-value="s">S</button>
<button class="key" data-value="d">D</button>
<button class="key" data-value="f">F</button>
<button class="key" data-value="g">G</button>
<button class="key" data-value="h">H</button>
<button class="key" data-value="j">J</button>
<button class="key" data-value="k">K</button>
<button class="key" data-value="l">L</button>
<button class="key" data-value=";">:<br>;</button>
<button class="key" data-value="'">"<br>'</button>
<button class="key wide" data-key="Enter">Enter</button>
</div>
<div class="row">
<button class="key extra-wide" data-key="Shift">Shift</button>
<button class="key" data-value="z">Z</button>
<button class="key" data-value="x">X</button>
<button class="key" data-value="c">C</button>
<button class="key" data-value="v">V</button>
<button class="key" data-value="b">B</button>
<button class="key" data-value="n">N</button>
<button class="key" data-value="m">M</button>
<button class="key" data-value=","><<br>,</button>
<button class="key" data-value=".">><br>.</button>
<button class="key" data-value="/">?<br>/</button>
<button class="key extra-wide" data-key="Shift">Shift</button>
</div>
<div class="row">
<button class="key" data-key="Control">Ctrl</button>
<button class="key" data-key="Alt">Alt</button>
<button class="key space" data-value=" ">Space</button>
<button class="key" data-key="Alt">Alt</button>
<button class="key" data-key="Control">Ctrl</button>
<button class="key" data-key="ArrowLeft">←</button>
<button class="key" data-key="ArrowUp">↑</button>
<button class="key" data-key="ArrowDown">↓</button>
<button class="key" data-key="ArrowRight">→</button>
</div>
</div>
<div class="controls">
<button class="control" id="clear">Clear</button>
<button class="control" id="copy">Copy Text</button>
<label class="rgb">
RGB
<input type="color" id="rgbColor" value="#7c3aed">
</label>
</div>
<div class="status">
Click a key or use your physical keyboard
</div>
</div>
</div>
<script>
const editor = document.getElementById("editor");
const keys = document.querySelectorAll(".key");
let caps = false;
let shift = false;
function insertText(text) {
const start = editor.selectionStart;
const end = editor.selectionEnd;
editor.value =
editor.value.substring(0, start) +
text +
editor.value.substring(end);
editor.selectionStart = editor.selectionEnd = start + text.length;
editor.focus();
}
function pressKey(key) {
if (key === "Backspace") {
const start = editor.selectionStart;
const end = editor.selectionEnd;
if (start !== end) {
editor.setRangeText("", start, end, "start");
} else if (start > 0) {
editor.setRangeText("", start - 1, start, "start");
}
return;
}
if (key === "Enter") {
insertText("\n");
return;
}
if (key === "Tab") {
insertText("\t");
return;
}
if (key === "CapsLock") {
caps = !caps;
return;
}
if (key === "Shift") {
shift = !shift;
return;
}
if (key === " ") {
insertText(" ");
return;
}
if (key.length === 1) {
let char = key;
if (/[a-z]/i.test(char)) {
if (caps !== shift) {
char = char.toUpperCase();
} else {
char = char.toLowerCase();
}
}
insertText(char);
}
}
keys.forEach(button => {
button.addEventListener("click", () => {
const value = button.dataset.value;
const key = button.dataset.key;
if (value !== undefined) {
pressKey(value);
} else if (key) {
pressKey(key);
}
button.classList.add("active");
setTimeout(() => {
button.classList.remove("active");
}, 100);
});
});
document.addEventListener("keydown", event => {
const physicalKey = event.key;
if (
["Tab", "Backspace", "Enter", "ArrowLeft",
"ArrowRight", "ArrowUp", "ArrowDown"].includes(physicalKey)
) {
event.preventDefault();
}
if (physicalKey === "CapsLock") {
caps = !caps;
}
if (physicalKey === "Shift") {
shift = true;
}
if (physicalKey === "Backspace") {
pressKey("Backspace");
}
else if (physicalKey === "Enter") {
pressKey("Enter");
}
else if (physicalKey === "Tab") {
pressKey("Tab");
}
else if (physicalKey.length === 1) {
insertText(physicalKey);
}
const matching = [...keys].find(button => {
return button.dataset.key === physicalKey;
});
if (matching) {
matching.classList.add("active");
}
});
document.addEventListener("keyup", event => {
if (event.key === "Shift") {
shift = false;
}
const matching = [...keys].find(button => {
return button.dataset.key === event.key;
});
if (matching) {
matching.classList.remove("active");
}
});
document.getElementById("clear").addEventListener("click", () => {
editor.value = "";
editor.focus();
});
document.getElementById("copy").addEventListener("click", async () => {
await navigator.clipboard.writeText(editor.value);
const button = document.getElementById("copy");
const oldText = button.textContent;
button.textContent = "Copied ✓";
setTimeout(() => {
button.textContent = oldText;
}, 1200);
});
document.getElementById("rgbColor").addEventListener("input", event => {
const color = event.target.value;
document.documentElement.style.setProperty(
"--rgb-color",
color
);
document.querySelectorAll(".key").forEach(key => {
key.style.setProperty("--key-color", color);
});
});
</script>
</body>
</html>