43 lines
1.2 KiB
TypeScript
43 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
|
|
interface Props {
|
|
title: string;
|
|
open: boolean;
|
|
onClose: () => void;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function AdminDialog({ title, open, onClose, children }: Props) {
|
|
useEffect(() => {
|
|
function onKey(e: KeyboardEvent) {
|
|
if (e.key === "Escape") onClose();
|
|
}
|
|
if (open) document.addEventListener("keydown", onKey);
|
|
return () => document.removeEventListener("keydown", onKey);
|
|
}, [open, onClose]);
|
|
|
|
if (!open) return null;
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
|
|
onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
|
|
>
|
|
<div className="w-full max-w-md rounded-xl bg-white shadow-xl">
|
|
<div className="flex items-center justify-between border-b border-neutral-200 px-6 py-4">
|
|
<h2 className="text-base font-semibold text-neutral-900">{title}</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-neutral-400 hover:text-neutral-600 transition-colors text-lg leading-none"
|
|
aria-label="Close"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div className="px-6 py-5">{children}</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|