import { Component, Show, onMount, onCleanup, createEffect } from 'solid-js'; import { Portal } from 'solid-js/web'; export interface ConfirmDialogProps { isOpen: boolean; title: string; message: string; description?: string; confirmLabel?: string; cancelLabel?: string; isDangerous?: boolean; isLoading?: boolean; onConfirm: () => void | Promise; onCancel: () => void; } /** * ConfirmDialog - Modal confirmation dialog matching ChatGPT/Claude patterns * * Features: * - Center-screen modal with backdrop * - Keyboard navigation (Escape to cancel, Tab between buttons) * - Accessibility support (ARIA labels, focus management) * - Danger mode for destructive actions (red button) * - Loading state for async operations * * @example * handleDelete()} * onCancel={() => setShowDialog(false)} * /> */ export const ConfirmDialog: Component = (props) => { let dialogRef: HTMLDivElement | undefined; let confirmButtonRef: HTMLButtonElement | undefined; // Handle keyboard events const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { e.preventDefault(); props.onCancel(); } }; // Lock body scroll when dialog is open createEffect(() => { if (props.isOpen) { document.body.style.overflow = 'hidden'; window.addEventListener('keydown', handleKeyDown); // Focus the dialog on next tick setTimeout(() => { confirmButtonRef?.focus(); }, 0); } else { document.body.style.overflow = ''; window.removeEventListener('keydown', handleKeyDown); } }); // Cleanup on unmount onCleanup(() => { document.body.style.overflow = ''; window.removeEventListener('keydown', handleKeyDown); }); const handleConfirm = async () => { await props.onConfirm(); }; const handleBackdropClick = (e: MouseEvent) => { if (e.target === e.currentTarget) { props.onCancel(); } }; return ( {/* Backdrop */}