62 lines
2.2 KiB
TypeScript
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>
|
|
)
|
|
}
|