Files
dndextended/src/app/charactercreator/components/Modal.tsx
T
Alexander Harding a3ea76fdff Vibecode central
2026-07-31 19:50:55 -04:00

65 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { type ReactNode, useEffect } from "react";
interface ModalProps {
open: boolean;
onClose: () => void;
title: string;
children: ReactNode;
wide?: boolean;
/**
* When true, X + Esc prompt for confirmation before closing.
* Backdrop clicks never close — user must use X.
*/
confirmClose?: boolean;
confirmMessage?: string;
}
export default function Modal({
open,
onClose,
title,
children,
wide,
confirmClose,
confirmMessage = "Discard changes? Any unsaved data will be lost.",
}: ModalProps) {
const requestClose = () => {
if (confirmClose && !window.confirm(confirmMessage)) return;
onClose();
};
useEffect(() => {
if (!open) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") requestClose();
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open, confirmClose]);
if (!open) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4">
<div
onClick={(e) => e.stopPropagation()}
className={`bg-neutral-900 border border-neutral-700 rounded-lg shadow-2xl w-full ${wide ? "max-w-4xl" : "max-w-lg"} max-h-[90vh] overflow-y-auto`}
>
<div className="flex items-center justify-between px-6 py-4 border-b border-neutral-700">
<h2 className="text-lg font-semibold text-neutral-100">{title}</h2>
<button
onClick={requestClose}
className="text-neutral-400 hover:text-neutral-100 text-2xl leading-none"
aria-label="Close"
>
×
</button>
</div>
<div className="p-6">{children}</div>
</div>
</div>
);
}