index.tsx 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import { Dialog, Transition } from '@headlessui/react'
  2. import { Fragment } from 'react'
  3. import { XMarkIcon } from '@heroicons/react/24/outline'
  4. // https://headlessui.com/react/dialog
  5. type IModal = {
  6. className?: string
  7. wrapperClassName?: string
  8. isShow: boolean
  9. onClose: () => void
  10. title?: React.ReactNode
  11. description?: React.ReactNode
  12. children: React.ReactNode
  13. closable?: boolean
  14. overflowVisible?: boolean
  15. }
  16. export default function Modal({
  17. className,
  18. wrapperClassName,
  19. isShow,
  20. onClose,
  21. title,
  22. description,
  23. children,
  24. closable = false,
  25. overflowVisible = false,
  26. }: IModal) {
  27. return (
  28. <Transition appear show={isShow} as={Fragment}>
  29. <Dialog as="div" className={`relative z-10 ${wrapperClassName}`} onClose={onClose}>
  30. <Transition.Child
  31. as={Fragment}
  32. enter="ease-out duration-300"
  33. enterFrom="opacity-0"
  34. enterTo="opacity-100"
  35. leave="ease-in duration-200"
  36. leaveFrom="opacity-100"
  37. leaveTo="opacity-0"
  38. >
  39. <div className="fixed inset-0 bg-black bg-opacity-25" />
  40. </Transition.Child>
  41. <div className="fixed inset-0 overflow-y-auto">
  42. <div className="flex min-h-full items-center justify-center p-4 text-center">
  43. <Transition.Child
  44. as={Fragment}
  45. enter="ease-out duration-300"
  46. enterFrom="opacity-0 scale-95"
  47. enterTo="opacity-100 scale-100"
  48. leave="ease-in duration-200"
  49. leaveFrom="opacity-100 scale-100"
  50. leaveTo="opacity-0 scale-95"
  51. >
  52. <Dialog.Panel className={`w-full max-w-md transform ${overflowVisible ? 'overflow-visible' : 'overflow-hidden'} rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all ${className}`}>
  53. {title && <Dialog.Title
  54. as="h3"
  55. className="text-lg font-medium leading-6 text-gray-900"
  56. >
  57. {title}
  58. </Dialog.Title>}
  59. {description && <Dialog.Description className='text-gray-500 text-xs font-normal mt-2'>
  60. {description}
  61. </Dialog.Description>}
  62. {closable
  63. && <div className='absolute top-6 right-6 w-5 h-5 rounded-2xl flex items-center justify-center hover:cursor-pointer hover:bg-gray-100'>
  64. <XMarkIcon className='w-4 h-4 text-gray-500' onClick={onClose} />
  65. </div>}
  66. {children}
  67. </Dialog.Panel>
  68. </Transition.Child>
  69. </div>
  70. </div>
  71. </Dialog>
  72. </Transition>
  73. )
  74. }