| 4dfd09b | | | 1 | "use client"; |
| 4dfd09b | | | 2 | |
| 4dfd09b | | | 3 | import { useRef, useEffect } from "react"; |
| 4dfd09b | | | 4 | |
| 4dfd09b | | | 5 | export interface DialogProps { |
| 4dfd09b | | | 6 | open: boolean; |
| 4dfd09b | | | 7 | onClose: () => void; |
| 4dfd09b | | | 8 | title: string; |
| 4dfd09b | | | 9 | children: React.ReactNode; |
| 4dfd09b | | | 10 | actions?: React.ReactNode; |
| 4dfd09b | | | 11 | className?: string; |
| 4dfd09b | | | 12 | } |
| 4dfd09b | | | 13 | |
| 4dfd09b | | | 14 | export function Dialog({ |
| 4dfd09b | | | 15 | open, |
| 4dfd09b | | | 16 | onClose, |
| 4dfd09b | | | 17 | title, |
| 4dfd09b | | | 18 | children, |
| 4dfd09b | | | 19 | actions, |
| 4dfd09b | | | 20 | className = "", |
| 4dfd09b | | | 21 | }: DialogProps) { |
| 4dfd09b | | | 22 | const ref = useRef<HTMLDialogElement>(null); |
| 4dfd09b | | | 23 | |
| 4dfd09b | | | 24 | useEffect(() => { |
| 4dfd09b | | | 25 | const dialog = ref.current; |
| 4dfd09b | | | 26 | if (!dialog) return; |
| 4dfd09b | | | 27 | |
| 4dfd09b | | | 28 | if (open && !dialog.open) { |
| 4dfd09b | | | 29 | dialog.showModal(); |
| 4dfd09b | | | 30 | } else if (!open && dialog.open) { |
| 4dfd09b | | | 31 | dialog.close(); |
| 4dfd09b | | | 32 | } |
| 4dfd09b | | | 33 | }, [open]); |
| 4dfd09b | | | 34 | |
| 4dfd09b | | | 35 | return ( |
| 4dfd09b | | | 36 | <dialog |
| 4dfd09b | | | 37 | ref={ref} |
| 4dfd09b | | | 38 | onClose={onClose} |
| 4dfd09b | | | 39 | onClick={(e) => { |
| 4dfd09b | | | 40 | if (e.target === ref.current) onClose(); |
| 4dfd09b | | | 41 | }} |
| ab61b9d | | | 42 | className={className} |
| 4dfd09b | | | 43 | style={{ |
| 4dfd09b | | | 44 | backgroundColor: "var(--bg-card)", |
| 4dfd09b | | | 45 | border: "1px solid var(--border-subtle)", |
| 4dfd09b | | | 46 | color: "var(--text-primary)", |
| ab61b9d | | | 47 | width: "100%", |
| ab61b9d | | | 48 | maxWidth: "28rem", |
| ab61b9d | | | 49 | margin: "auto", |
| ab61b9d | | | 50 | boxShadow: "0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06)", |
| ab61b9d | | | 51 | overflow: "hidden", |
| 4dfd09b | | | 52 | }} |
| 4dfd09b | | | 53 | > |
| ab61b9d | | | 54 | <div |
| ab61b9d | | | 55 | className="px-6 pt-6 pb-4" |
| ab61b9d | | | 56 | style={{ borderBottom: "1px solid var(--border-subtle)" }} |
| ab61b9d | | | 57 | > |
| ab61b9d | | | 58 | <h2 className="text-lg">{title}</h2> |
| ab61b9d | | | 59 | </div> |
| ab61b9d | | | 60 | <div className="px-6 py-5">{children}</div> |
| 4dfd09b | | | 61 | {actions && ( |
| ab61b9d | | | 62 | <div |
| ab61b9d | | | 63 | className="flex gap-3 px-6 py-4 justify-end" |
| ab61b9d | | | 64 | style={{ |
| ab61b9d | | | 65 | borderTop: "1px solid var(--border-subtle)", |
| ab61b9d | | | 66 | backgroundColor: "var(--bg-inset)", |
| ab61b9d | | | 67 | }} |
| ab61b9d | | | 68 | > |
| ab61b9d | | | 69 | {actions} |
| ab61b9d | | | 70 | </div> |
| 4dfd09b | | | 71 | )} |
| 4dfd09b | | | 72 | </dialog> |
| 4dfd09b | | | 73 | ); |
| 4dfd09b | | | 74 | } |