2025-12-19 17:52:14 +01:00

62 lines
2.2 KiB
TypeScript

'use client'
import { Fragment } from 'react'
import { Dialog, Transition } from '@headlessui/react'
type ModalProps = {
open: boolean
onClose: () => void
title?: string
children?: React.ReactNode
footer?: React.ReactNode
icon?: React.ReactNode
}
export default function Modal({
open,
onClose,
title,
children,
footer,
icon,
}: ModalProps) {
return (
<Transition show={open} as={Fragment}>
<Dialog as="div" className="relative z-50" onClose={onClose}>
{/* Backdrop */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100"
leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500/75 dark:bg-gray-900/50" />
</Transition.Child>
{/* Modal Panel */}
<div className="fixed inset-0 z-50 flex items-center justify-center px-4 py-6 sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300" enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200" leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative w-full max-w-lg transform overflow-hidden rounded-lg bg-white p-6 text-left shadow-xl transition-all dark:bg-gray-800 dark:outline dark:-outline-offset-1 dark:outline-white/10">
{icon && (
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-500/10">
{icon}
</div>
)}
{title && (
<Dialog.Title className="text-base font-semibold text-gray-900 dark:text-white">
{title}
</Dialog.Title>
)}
<div className="mt-2 text-sm text-gray-700 dark:text-gray-300">{children}</div>
{footer && <div className="mt-6 flex justify-end gap-3">{footer}</div>}
</Dialog.Panel>
</Transition.Child>
</div>
</Dialog>
</Transition>
)
}