Greasy Fork is available in English.
A lightweight Tampermonkey HUD that displays real-time keypresses with a terminal-inspired aesthetic.
// ==UserScript==
// @name Keystroke Visualizer
// @namespace http://tampermonkey.net/
// @version 2026-03-12
// @description A lightweight Tampermonkey HUD that displays real-time keypresses with a terminal-inspired aesthetic.
// @author Samir
// @match https://*/*
// @icon https://www.clipartmax.com/png/middle/152-1524168_open-tab-key-icon-png.png
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const display = document.createElement('div');
display.id = 'tm-keystroke-display';
display.innerText = 'Press key...';
const style = document.createElement('style');
style.innerHTML = `
#tm-keystroke-display {
position: fixed;
top: 50px;
right: 50px;
padding: 12px 20px;
/* Restored original colors */
background: rgba(0, 0, 0, 0.85);
color: #00ff00; /* Green */
border: 1px solid #444; /* Original border */
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;
font-size: 19px;
font-weight: bold;
border-radius: 8px;
z-index: 1000000;
cursor: move;
user-select: none;
box-shadow: 0 4px 15px rgba(0,0,0,0.4);
min-width: 100px;
text-align: center;
pointer-events: auto;
opacity: 1;
}
/* Blink animation for repeated keys */
.key-press-animation {
animation: key-blink 0.12s ease-out;
}
@keyframes key-blink {
0% { background: rgba(30, 30, 30, 0.9); scale: 0.8; color: #06402B} /* Dim and slightly lighter bg */
100% { background: rgba(0, 0, 0, 0.85); scale: 1; color: #00ff00} /* Back to normal */
}
`;
document.head.appendChild(style);
document.body.appendChild(display);
window.addEventListener('keydown', (e) => {
let keyText = [];
if (e.metaKey) keyText.push('⌘');
if (e.ctrlKey) keyText.push('Ctrl');
if (e.altKey) keyText.push('⌥');
if (e.shiftKey && e.key !== 'Shift') keyText.push('⇧');
const mainKey = e.key === ' ' ? 'SPACE' : e.key.toUpperCase();
if (!['META', 'CONTROL', 'ALT', 'SHIFT'].includes(mainKey)) {
keyText.push(mainKey);
}
display.innerText = keyText.join(' + ');
display.classList.remove('key-press-animation');
void display.offsetWidth; // Force reflow
display.classList.add('key-press-animation');
clearTimeout(display.timeout);
display.timeout = setTimeout(() => {
display.innerText = '...';
display.classList.remove('key-press-animation');
}, 1800);
}, true);
//draggable
let isDragging = false;
let offset = { x: 0, y: 0 };
display.addEventListener('mousedown', (e) => {
isDragging = true;
offset.x = e.clientX - display.getBoundingClientRect().left;
offset.y = e.clientY - display.getBoundingClientRect().top;
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
display.style.left = (e.clientX - offset.x) + 'px';
display.style.top = (e.clientY - offset.y) + 'px';
display.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
})();