import { styled } from "goober"; import { forwardRef, useEffect, useRef } from "react"; import { Button } from "./button.js"; import { Heading } from "./heading.js"; interface ModalProps { isOpen: boolean; onClose: () => void; heading: string; text?: string; children?: React.ReactNode; confirmText?: string; cancelText?: string; onConfirm?: () => void; onCancel?: () => void; showButtons?: boolean; className?: string; wide?: boolean; } const ModalContent = styled("dialog")<{ wide?: boolean }>` background-color: var(--j-background); border-radius: var(--j-radius-lg); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); border: 1px solid var(--j-border-color); ${(props) => (props.wide ? "max-width: 60vw;" : "max-width: 32rem;")} margin-block: auto; margin-inline: auto; &::backdrop { background-color: rgba(0, 0, 0, 0.7); } `; const ModalHeader = styled("div")` display: flex; justify-content: space-between; align-items: flex-start; padding: 1.5rem 1.5rem 0 1.5rem; gap: 1rem; `; const ModalBody = styled("div")` padding: 1rem 1.5rem; flex: 1; `; const ModalFooter = styled("div")` display: flex; justify-content: flex-end; gap: 0.75rem; padding: 0 1.5rem 1.5rem 1.5rem; `; const CloseButton = styled("button")` background: none; border: none; cursor: pointer; padding: 0.25rem; border-radius: var(--j-radius-sm); color: var(--j-text-color); font-size: 1.25rem; line-height: 1; display: flex; align-items: center; justify-content: center; min-width: 2rem; min-height: 2rem; &:hover { background-color: var(--j-foreground); } &:focus-visible { outline: 2px solid var(--j-border-focus); outline-offset: 2px; } `; export const Modal = forwardRef( ( { isOpen, onClose, heading, text, children, confirmText = "Confirm", cancelText = "Cancel", onConfirm, onCancel, showButtons = true, className, wide = false, }, ref, ) => { const modalRef = useRef(null); useEffect(() => { if (isOpen) { modalRef.current?.showModal(); } else { onClose(); modalRef.current?.close(); } }, [isOpen, onClose]); const handleConfirm = () => { onConfirm?.(); onClose(); }; const handleCancel = () => { onCancel?.(); onClose(); }; if (!isOpen) return null; return ( {heading} × {text && (

{text}

)} {children}
{showButtons && ( )}
); }, ); Modal.displayName = "Modal";