Files
TicketingSystem/client/src/components/Modal.tsx
T
josh 27d2ab0f0d Add ESLint + Prettier + EditorConfig tooling at repo root
v1.0 Phase 1.1 — repo-wide lint/format baseline.

- eslint.config.mjs (flat config) lints server, client, shared
- .prettierrc.json, .prettierignore, .editorconfig, .nvmrc
- Root package.json holds shared devDeps; per-package scripts keep
  their typecheck + test runners
- Fix 7 lint issues surfaced by the baseline run:
  - TicketDetail.tsx: replace ternary-with-side-effects with if/else
  - admin/Users.tsx: escape apostrophe in JSX
  - errorHandler.ts: typed err as unknown with ErrorLike refinement
  - users.ts: Prisma.UserUpdateInput instead of Record<string, any>
  - seed.ts: drop unused goddard binding
- Run prettier across tracked sources for a clean formatting baseline
2026-04-18 14:47:34 -04:00

41 lines
1.3 KiB
TypeScript

import { ReactNode, useEffect } from 'react';
import { X } from 'lucide-react';
interface ModalProps {
title: string;
onClose: () => void;
children: ReactNode;
size?: 'md' | 'lg';
}
export default function Modal({ title, onClose, children, size = 'md' }: ModalProps) {
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('keydown', handler);
return () => document.removeEventListener('keydown', handler);
}, [onClose]);
return (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
onClick={(e) => {
if (e.target === e.currentTarget) onClose();
}}
>
<div
className={`bg-gray-900 border border-gray-800 rounded-xl shadow-2xl w-full mx-4 ${size === 'lg' ? 'max-w-2xl' : 'max-w-md'}`}
>
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-800">
<h3 className="text-base font-semibold text-gray-100">{title}</h3>
<button onClick={onClose} className="text-gray-500 hover:text-gray-300 transition-colors">
<X size={18} />
</button>
</div>
<div className="px-6 py-5">{children}</div>
</div>
</div>
);
}