Vibecode central

This commit is contained in:
Alexander Harding
2026-07-31 19:50:55 -04:00
parent 1362f28585
commit a3ea76fdff
67 changed files with 6287 additions and 202 deletions
@@ -0,0 +1,64 @@
"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>
);
}