You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
2 年之前
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react'
  2. import { Fragment } from 'react'
  3. import { RiCloseLine } from '@remixicon/react'
  4. import classNames from '@/utils/classnames'
  5. import { noop } from 'lodash-es'
  6. // https://headlessui.com/react/dialog
  7. type IModal = {
  8. className?: string
  9. wrapperClassName?: string
  10. isShow: boolean
  11. onClose?: () => void
  12. title?: React.ReactNode
  13. description?: React.ReactNode
  14. children?: React.ReactNode
  15. closable?: boolean
  16. overflowVisible?: boolean
  17. highPriority?: boolean // For modals that need to appear above dropdowns
  18. }
  19. export default function Modal({
  20. className,
  21. wrapperClassName,
  22. isShow,
  23. onClose = noop,
  24. title,
  25. description,
  26. children,
  27. closable = false,
  28. overflowVisible = false,
  29. highPriority = false,
  30. }: IModal) {
  31. return (
  32. <Transition appear show={isShow} as={Fragment}>
  33. <Dialog as="div" className={classNames('relative', highPriority ? 'z-[1100]' : 'z-[60]', wrapperClassName)} onClose={onClose}>
  34. <TransitionChild>
  35. <div className={classNames(
  36. 'fixed inset-0 bg-background-overlay',
  37. 'duration-300 ease-in data-[closed]:opacity-0',
  38. 'data-[enter]:opacity-100',
  39. 'data-[leave]:opacity-0',
  40. )} />
  41. </TransitionChild>
  42. <div
  43. className="fixed inset-0 overflow-y-auto"
  44. onClick={(e) => {
  45. e.preventDefault()
  46. e.stopPropagation()
  47. }}
  48. >
  49. <div className="flex min-h-full items-center justify-center p-4 text-center">
  50. <TransitionChild>
  51. <DialogPanel className={classNames(
  52. 'w-full max-w-[480px] rounded-2xl bg-components-panel-bg p-6 text-left align-middle shadow-xl transition-all',
  53. overflowVisible ? 'overflow-visible' : 'overflow-hidden',
  54. 'duration-100 ease-in data-[closed]:scale-95 data-[closed]:opacity-0',
  55. 'data-[enter]:scale-100 data-[enter]:opacity-100',
  56. 'data-[enter]:scale-95 data-[leave]:opacity-0',
  57. className,
  58. )}>
  59. {title && <DialogTitle
  60. as="h3"
  61. className="title-2xl-semi-bold text-text-primary"
  62. >
  63. {title}
  64. </DialogTitle>}
  65. {description && <div className='body-md-regular mt-2 text-text-secondary'>
  66. {description}
  67. </div>}
  68. {closable
  69. && <div className='absolute right-6 top-6 z-10 flex h-5 w-5 items-center justify-center rounded-2xl hover:cursor-pointer hover:bg-state-base-hover'>
  70. <RiCloseLine className='h-4 w-4 text-text-tertiary' onClick={
  71. (e) => {
  72. e.stopPropagation()
  73. onClose()
  74. }
  75. } />
  76. </div>}
  77. {children}
  78. </DialogPanel>
  79. </TransitionChild>
  80. </div>
  81. </div>
  82. </Dialog>
  83. </Transition>
  84. )
  85. }