Docs
Go back
Component by
OV
OblivionPress Start
PWR_ON
TSX
arcade-button
"use client"
import React, { useState } from "react"
import { cn } from "@/lib/utils"
export const componentMeta = {
name: "Arcade Button",
description: "An incredibly tactile physical switch with extreme depth. Feels exactly like pressing a heavy mechanical arcade button.",
props: {
className: { type: "string", description: "Additional CSS classes", default: '""' }
}
}
export default function ArcadeButton({ className }: { className?: string }) {
const [pressed, setPressed] = useState(false)
return (
<div className={cn("flex flex-col items-center justify-center p-12 gap-8", className)}>
<div className="text-zinc-500 text-sm font-semibold tracking-[0.2em] uppercase">Press Start</div>
{/* Bezel / Base of the button */}
<div className="relative w-52 h-52 rounded-full bg-gradient-to-b from-zinc-700 to-zinc-900 flex items-center justify-center shadow-[0_15px_30px_rgba(0,0,0,0.6),inset_0_2px_3px_rgba(255,255,255,0.2)] border-2 border-zinc-950 select-none">
{/* Inner plastic trench */}
<div className="relative w-40 h-40 rounded-full bg-zinc-950 flex items-center justify-center shadow-[inset_0_12px_24px_rgba(0,0,0,0.9)] overflow-hidden">
{/* Highlight rim in the trench */}
<div className="absolute inset-0 rounded-full border-[6px] border-zinc-900 blur-[2px]" />
{/* Actual Red Button Cap */}
<button
onMouseDown={() => setPressed(true)}
onMouseUp={() => setPressed(false)}
onMouseLeave={() => setPressed(false)}
onTouchStart={() => setPressed(true)}
onTouchEnd={() => setPressed(false)}
className={cn(
"relative w-32 h-32 rounded-full transition-all duration-[50ms] focus:outline-none flex items-center justify-center group overflow-hidden border-2",
pressed
? "bg-red-700 border-red-800 translate-y-3 shadow-[inset_0_20px_30px_rgba(0,0,0,0.7)]"
: "bg-red-500 border-red-400 translate-y-[-8px] shadow-[0_14px_0_#7f1d1d,0_24px_24px_rgba(0,0,0,0.7),inset_0_8px_16px_rgba(255,255,255,0.4)]"
)}
>
{/* Glassy dome glare - top */}
<div className={cn(
"absolute top-2 left-1/2 -translate-x-1/2 w-[80%] h-[30%] bg-white/40 rounded-[50%] blur-[2px] transition-opacity",
pressed ? "opacity-20" : "opacity-80"
)} />
{/* Glassy dome glare - side */}
<div className="absolute right-3 top-1/2 -translate-y-1/2 w-2 h-[60%] bg-white/20 rounded-[50%] blur-[3px]" />
{/* Internal button text/icon (optional, but adds to the vibe) */}
<div className={cn(
"text-white font-black tracking-widest text-2xl drop-shadow-[0_2px_2px_rgba(0,0,0,0.5)] transition-transform",
pressed ? "scale-95 text-red-100" : "scale-100"
)}>
P1
</div>
</button>
</div>
</div>
{/* Optional status light to visualize the output */}
<div className="flex items-center gap-3">
<div className={cn(
"w-3 h-3 rounded-full transition-colors duration-75 shadow-sm",
pressed ? "bg-green-500 shadow-[0_0_15px_rgba(34,197,94,0.8)]" : "bg-zinc-800 shadow-[inset_0_2px_4px_rgba(0,0,0,0.5)]"
)} />
<span className="text-zinc-600 text-xs font-mono font-bold">PWR_ON</span>
</div>
</div>
)
}"use client"
import React, { useState } from "react"
import { cn } from "@/lib/utils"
export const componentMeta = {
name: "Arcade Button",
description: "An incredibly tactile physical switch with extreme depth. Feels exactly like pressing a heavy mechanical arcade button.",
props: {
className: { type: "string", description: "Additional CSS classes", default: '""' }
}
}
export default function ArcadeButton({ className }: { className?: string }) {
const [pressed, setPressed] = useState(false)
return (
<div className={cn("flex flex-col items-center justify-center p-12 gap-8", className)}>
<div className="text-zinc-500 text-sm font-semibold tracking-[0.2em] uppercase">Press Start</div>
{/* Bezel / Base of the button */}
<div className="relative w-52 h-52 rounded-full bg-gradient-to-b from-zinc-700 to-zinc-900 flex items-center justify-center shadow-[0_15px_30px_rgba(0,0,0,0.6),inset_0_2px_3px_rgba(255,255,255,0.2)] border-2 border-zinc-950 select-none">
{/* Inner plastic trench */}
<div className="relative w-40 h-40 rounded-full bg-zinc-950 flex items-center justify-center shadow-[inset_0_12px_24px_rgba(0,0,0,0.9)] overflow-hidden">
{/* Highlight rim in the trench */}
<div className="absolute inset-0 rounded-full border-[6px] border-zinc-900 blur-[2px]" />
{/* Actual Red Button Cap */}
<button
onMouseDown={() => setPressed(true)}
onMouseUp={() => setPressed(false)}
onMouseLeave={() => setPressed(false)}
onTouchStart={() => setPressed(true)}
onTouchEnd={() => setPressed(false)}
className={cn(
"relative w-32 h-32 rounded-full transition-all duration-[50ms] focus:outline-none flex items-center justify-center group overflow-hidden border-2",
pressed
? "bg-red-700 border-red-800 translate-y-3 shadow-[inset_0_20px_30px_rgba(0,0,0,0.7)]"
: "bg-red-500 border-red-400 translate-y-[-8px] shadow-[0_14px_0_#7f1d1d,0_24px_24px_rgba(0,0,0,0.7),inset_0_8px_16px_rgba(255,255,255,0.4)]"
)}
>
{/* Glassy dome glare - top */}
<div className={cn(
"absolute top-2 left-1/2 -translate-x-1/2 w-[80%] h-[30%] bg-white/40 rounded-[50%] blur-[2px] transition-opacity",
pressed ? "opacity-20" : "opacity-80"
)} />
{/* Glassy dome glare - side */}
<div className="absolute right-3 top-1/2 -translate-y-1/2 w-2 h-[60%] bg-white/20 rounded-[50%] blur-[3px]" />
{/* Internal button text/icon (optional, but adds to the vibe) */}
<div className={cn(
"text-white font-black tracking-widest text-2xl drop-shadow-[0_2px_2px_rgba(0,0,0,0.5)] transition-transform",
pressed ? "scale-95 text-red-100" : "scale-100"
)}>
P1
</div>
</button>
</div>
</div>
{/* Optional status light to visualize the output */}
<div className="flex items-center gap-3">
<div className={cn(
"w-3 h-3 rounded-full transition-colors duration-75 shadow-sm",
pressed ? "bg-green-500 shadow-[0_0_15px_rgba(34,197,94,0.8)]" : "bg-zinc-800 shadow-[inset_0_2px_4px_rgba(0,0,0,0.5)]"
)} />
<span className="text-zinc-600 text-xs font-mono font-bold">PWR_ON</span>
</div>
</div>
)
}Save to favoritesCopy to Figma
React
Arcade Button
An incredibly tactile physical switch with extreme depth. Feels exactly like pressing a heavy mechanical arcade button.
Installation
$ npx @cosmoo/oblivion add arcade-buttonDependencies
npm install Usage Example
tsx
import ArcadeButton from "@/components/oblivion/arcade-button"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<ArcadeButton />
</div>
)
}import ArcadeButton from "@/components/oblivion/arcade-button"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<ArcadeButton />
</div>
)
}