| | |
| | | import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react' |
| | | import { Dialog, Transition } from '@headlessui/react' |
| | | import { Fragment } from 'react' |
| | | import { RiCloseLine } from '@remixicon/react' |
| | | import classNames from '@/utils/classnames' |
| | | import { noop } from 'lodash-es' |
| | | // https://headlessui.com/react/dialog |
| | | |
| | | type IModal = { |
| | |
| | | className, |
| | | wrapperClassName, |
| | | isShow, |
| | | onClose = noop, |
| | | onClose = () => { }, |
| | | title, |
| | | description, |
| | | children, |
| | |
| | | }: IModal) { |
| | | return ( |
| | | <Transition appear show={isShow} as={Fragment}> |
| | | <Dialog as="div" className={classNames('relative z-[60]', wrapperClassName)} onClose={onClose}> |
| | | <TransitionChild> |
| | | <div className={classNames( |
| | | 'fixed inset-0 bg-background-overlay', |
| | | 'duration-300 ease-in data-[closed]:opacity-0', |
| | | 'data-[enter]:opacity-100', |
| | | 'data-[leave]:opacity-0', |
| | | )} /> |
| | | </TransitionChild> |
| | | <Dialog as="div" className={classNames('relative z-50', wrapperClassName)} onClose={onClose}> |
| | | <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-background-overlay" /> |
| | | </Transition.Child> |
| | | |
| | | <div |
| | | className="fixed inset-0 overflow-y-auto" |
| | |
| | | }} |
| | | > |
| | | <div className="flex min-h-full items-center justify-center p-4 text-center"> |
| | | <TransitionChild> |
| | | <DialogPanel className={classNames( |
| | | <Transition.Child |
| | | as={Fragment} |
| | | enter="ease-out duration-300" |
| | | enterFrom="opacity-0 scale-95" |
| | | enterTo="opacity-100 scale-100" |
| | | leave="ease-in duration-200" |
| | | leaveFrom="opacity-100 scale-100" |
| | | leaveTo="opacity-0 scale-95" |
| | | > |
| | | <Dialog.Panel className={classNames( |
| | | 'w-full max-w-[480px] transform rounded-2xl bg-components-panel-bg p-6 text-left align-middle shadow-xl transition-all', |
| | | overflowVisible ? 'overflow-visible' : 'overflow-hidden', |
| | | 'duration-100 ease-in data-[closed]:opacity-0 data-[closed]:scale-95', |
| | | 'data-[enter]:opacity-100 data-[enter]:scale-100', |
| | | 'data-[leave]:opacity-0 data-[enter]:scale-95', |
| | | className, |
| | | )}> |
| | | {title && <DialogTitle |
| | | {title && <Dialog.Title |
| | | as="h3" |
| | | className="title-2xl-semi-bold text-text-primary" |
| | | > |
| | | {title} |
| | | </DialogTitle>} |
| | | {description && <div className='body-md-regular mt-2 text-text-secondary'> |
| | | </Dialog.Title>} |
| | | {description && <Dialog.Description className='text-text-secondary body-md-regular mt-2'> |
| | | {description} |
| | | </div>} |
| | | </Dialog.Description>} |
| | | {closable |
| | | && <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'> |
| | | <RiCloseLine className='h-4 w-4 text-text-tertiary' onClick={ |
| | | && <div className='absolute z-10 top-6 right-6 w-5 h-5 rounded-2xl flex items-center justify-center hover:cursor-pointer hover:bg-state-base-hover'> |
| | | <RiCloseLine className='w-4 h-4 text-text-tertiary' onClick={ |
| | | (e) => { |
| | | e.stopPropagation() |
| | | onClose() |
| | |
| | | } /> |
| | | </div>} |
| | | {children} |
| | | </DialogPanel> |
| | | </TransitionChild> |
| | | </Dialog.Panel> |
| | | </Transition.Child> |
| | | </div> |
| | | </div> |
| | | </Dialog> |