mirror of
https://github.com/Xevion/smart-rgb.git
synced 2025-12-14 04:13:10 -06:00
100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
import { useState } from "react";
|
|
import { Menu, X } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import "./Menu.css";
|
|
|
|
interface GameMenuProps {
|
|
onExit: () => void;
|
|
onSettings?: () => void;
|
|
}
|
|
|
|
export function GameMenu({ onExit, onSettings }: GameMenuProps) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
|
const [isClosing, setIsClosing] = useState(false);
|
|
|
|
const closeConfirmation = () => {
|
|
setIsClosing(true);
|
|
setTimeout(() => {
|
|
setShowConfirmation(false);
|
|
setIsClosing(false);
|
|
}, 200);
|
|
};
|
|
|
|
return (
|
|
<div className="fixed top-4 right-4 z-999 no-drag block-game-input">
|
|
{/* Hamburger/Close Button */}
|
|
<button
|
|
className="bg-[rgba(15,23,42,0.75)] border-none rounded-md text-white p-2 cursor-pointer flex items-center justify-center transition-colors duration-150 ease-[ease] hover:bg-[rgba(15,23,42,0.9)]"
|
|
onClick={() => setIsOpen((prev) => !prev)}
|
|
>
|
|
{isOpen ? <X size={20} /> : <Menu size={20} />}
|
|
</button>
|
|
|
|
{/* Dropdown Menu */}
|
|
{isOpen && (
|
|
<div className="absolute top-[calc(100%+0.5rem)] right-0 bg-[rgba(15,23,42,0.75)] rounded-md min-w-[140px] overflow-hidden">
|
|
<button
|
|
className={cn(
|
|
"w-full bg-transparent border-none text-white py-1.5 px-4 text-right cursor-pointer font-inter transition-[background-color] duration-150 ease-[ease] hover:bg-[rgba(255,255,255,0.06)]",
|
|
onSettings && "border-t border-white/10",
|
|
)}
|
|
onClick={() => {
|
|
setShowConfirmation(true);
|
|
setIsClosing(false);
|
|
setIsOpen(false);
|
|
}}
|
|
>
|
|
Exit
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
{/* Confirmation Dialog */}
|
|
{showConfirmation && (
|
|
<div
|
|
className={cn(
|
|
"fixed inset-0 bg-[rgba(0,0,0,0.5)] flex items-center justify-center z-[1000]",
|
|
isClosing ? "animate-[fadeOut_0.2s_ease-out_forwards]" : "animate-[fadeIn_0.2s_ease-out]",
|
|
)}
|
|
onClick={closeConfirmation}
|
|
>
|
|
<div
|
|
className={cn(
|
|
"bg-zinc-900 rounded-lg p-8 min-w-[300px] max-w-[400px] shadow-lg shadow-zinc-950/50",
|
|
isClosing ? "animate-[slideDown_0.2s_ease-out_forwards]" : "animate-[slideUp_0.2s_ease-out]",
|
|
)}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<h3 className="my-0 mb-4 text-white text-xl font-inter font-semibold">Are you sure?</h3>
|
|
<p className="my-0 mb-6 text-white/80 font-inter leading-normal text-pretty">
|
|
You will not be able to return to this game after exiting.
|
|
</p>
|
|
<div className="flex gap-3 justify-end">
|
|
<button
|
|
className="border-none rounded-md text-white px-5 cursor-pointer font-inter transition-colors duration-150 ease-in-out bg-white/10 hover:bg-white/15"
|
|
onClick={closeConfirmation}
|
|
>
|
|
Nevermind
|
|
</button>
|
|
<button
|
|
className="border-none rounded-md text-white px-5 cursor-pointer font-inter transition-[background-color] duration-150 ease-[ease] bg-red-500 font-medium hover:bg-red-400"
|
|
onClick={() => {
|
|
setIsClosing(true);
|
|
setTimeout(() => {
|
|
setShowConfirmation(false);
|
|
setIsClosing(false);
|
|
onExit();
|
|
}, 200);
|
|
}}
|
|
>
|
|
I'm sure
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|