Components
Keyboard Button
A button that looks and feels like a mechanical keyboard key, with visual depth and a satisfying click sound.
Preview
Installation
npx shadcn@latest add https://orbit.ruturaj.xyz/r/keyboard-buttonThe click sound is bundled with the component — no extra files needed.
Code
"use client";
import { ButtonHTMLAttributes, useEffect, useRef, useState } from "react";
const CLICK_SOUND = "data:audio/mp3;base64,...";
interface KeyboardButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
audioSrc?: string;
}
export function KeyboardButton({ children, className = "", disabled, audioSrc = CLICK_SOUND, ...props }: KeyboardButtonProps) {
const [pressed, setPressed] = useState(false);
const audioRef = useRef<HTMLAudioElement | null>(null);
useEffect(() => {
audioRef.current = audioSrc ? new Audio(audioSrc) : null;
}, [audioSrc]);
const isPressed = pressed && !disabled;
function playClick() {
const audio = audioRef.current;
if (!audio) return;
audio.currentTime = 0;
audio.play().catch(() => {});
}
return (
<button
{...props}
disabled={disabled}
onMouseDown={() => { setPressed(true); playClick(); }}
onMouseUp={() => setPressed(false)}
onMouseLeave={() => setPressed(false)}
onTouchStart={() => { setPressed(true); playClick(); }}
onTouchEnd={() => setPressed(false)}
className={`relative select-none rounded-[6px] border border-black/[0.12] bg-[#f0efea] px-5 py-2.5 text-sm font-medium tracking-wide text-zinc-700 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${className}`}
style={{
backgroundImage: isPressed
? "linear-gradient(to bottom, #e8e7e2, #e4e3de)"
: "linear-gradient(to bottom, #f5f4ef, #ebebE6)",
boxShadow: isPressed
? "inset 0 1px 0 rgba(255,255,255,0.4), 0 0 0 #b8b5b0"
: "inset 0 1px 0 rgba(255,255,255,0.8), 0 3px 0 #b8b5b0, 0 4px 5px rgba(0,0,0,0.08)",
transform: isPressed ? "translateY(3px)" : "translateY(0)",
transition: isPressed
? "none"
: "transform 80ms ease-out, box-shadow 80ms ease-out",
}}
>
{children}
</button>
);
}