47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
import { X } from "lucide-react";
|
|
import { useEffect, useId, useRef, type ReactNode } from "react";
|
|
|
|
interface Props {
|
|
title: string;
|
|
children: ReactNode;
|
|
onClose: () => void;
|
|
className?: string;
|
|
}
|
|
export function Dialog({ title, children, onClose, className = "" }: Props) {
|
|
const ref = useRef<HTMLDialogElement>(null);
|
|
const titleId = useId();
|
|
useEffect(() => {
|
|
const dialog = ref.current;
|
|
dialog?.showModal();
|
|
return () => {
|
|
dialog?.close();
|
|
};
|
|
}, []);
|
|
return (
|
|
<dialog
|
|
ref={ref}
|
|
className={`modal ${className}`}
|
|
aria-labelledby={titleId}
|
|
onCancel={(event) => {
|
|
event.preventDefault();
|
|
onClose();
|
|
}}
|
|
onClick={(event) => {
|
|
if (event.target === event.currentTarget) {
|
|
onClose();
|
|
}
|
|
}}
|
|
>
|
|
<div className="modal-content">
|
|
<header className="modal-header">
|
|
<h2 id={titleId}>{title}</h2>
|
|
<button type="button" className="icon-btn" aria-label="Cerrar" onClick={onClose}>
|
|
<X size={18} />
|
|
</button>
|
|
</header>
|
|
{children}
|
|
</div>
|
|
</dialog>
|
|
);
|
|
}
|