fix: clicking outside modal closes modal again (#2984)

This commit is contained in:
Ryan Cohen
2022-08-25 13:28:44 +09:00
committed by GitHub
parent b925857dfa
commit 1a0053221b
2 changed files with 82 additions and 72 deletions

View File

@@ -7,7 +7,7 @@ import { useLockBodyScroll } from '@app/hooks/useLockBodyScroll';
import globalMessages from '@app/i18n/globalMessages'; import globalMessages from '@app/i18n/globalMessages';
import { Transition } from '@headlessui/react'; import { Transition } from '@headlessui/react';
import type { MouseEvent } from 'react'; import type { MouseEvent } from 'react';
import { Fragment, useRef } from 'react'; import React, { Fragment, useRef } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
@@ -36,7 +36,9 @@ interface ModalProps {
children?: React.ReactNode; children?: React.ReactNode;
} }
const Modal = ({ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
(
{
title, title,
onCancel, onCancel,
onOk, onOk,
@@ -56,9 +58,12 @@ const Modal = ({
tertiaryButtonType = 'default', tertiaryButtonType = 'default',
tertiaryDisabled = false, tertiaryDisabled = false,
tertiaryText, tertiaryText,
loading = false,
onTertiary, onTertiary,
backdrop, backdrop,
}: ModalProps) => { },
parentRef
) => {
const intl = useIntl(); const intl = useIntl();
const modalRef = useRef<HTMLDivElement>(null); const modalRef = useRef<HTMLDivElement>(null);
useClickOutside(modalRef, () => { useClickOutside(modalRef, () => {
@@ -69,18 +74,20 @@ const Modal = ({
useLockBodyScroll(true, disableScrollLock); useLockBodyScroll(true, disableScrollLock);
return ReactDOM.createPortal( return ReactDOM.createPortal(
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div
className="fixed top-0 bottom-0 left-0 right-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70"
onKeyDown={(e) => {
if (e.key === 'Escape') {
typeof onCancel === 'function' && backgroundClickable
? onCancel()
: undefined;
}
}}
>
<Transition.Child <Transition.Child
appear
as="div"
className="fixed top-0 bottom-0 left-0 right-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70"
enter="transition opacity-0 duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition opacity-100 duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
ref={parentRef}
>
<Transition
appear
as={Fragment} as={Fragment}
enter="transition opacity-0 duration-300 transform scale-75" enter="transition opacity-0 duration-300 transform scale-75"
enterFrom="opacity-0 scale-75" enterFrom="opacity-0 scale-75"
@@ -88,29 +95,30 @@ const Modal = ({
leave="transition opacity-100 duration-300" leave="transition opacity-100 duration-300"
leaveFrom="opacity-100" leaveFrom="opacity-100"
leaveTo="opacity-0" leaveTo="opacity-0"
show={loading}
> >
<div style={{ position: 'absolute' }}> <div style={{ position: 'absolute' }}>
<LoadingSpinner /> <LoadingSpinner />
</div> </div>
</Transition.Child> </Transition>
<Transition.Child <Transition
as={Fragment} className="hide-scrollbar relative inline-block w-full transform overflow-auto bg-gray-700 px-4 pt-5 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-500 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
style={{
maxHeight: 'calc(100% - env(safe-area-inset-top) * 2)',
}}
appear
as="div"
enter="transition opacity-0 duration-300 transform scale-75" enter="transition opacity-0 duration-300 transform scale-75"
enterFrom="opacity-0 scale-75" enterFrom="opacity-0 scale-75"
enterTo="opacity-100 scale-100" enterTo="opacity-100 scale-100"
leave="transition opacity-100 duration-300" leave="transition opacity-100 duration-300"
leaveFrom="opacity-100" leaveFrom="opacity-100"
leaveTo="opacity-0" leaveTo="opacity-0"
> show={!loading}
<div
className="relative inline-block w-full transform overflow-auto bg-gray-700 px-4 pt-5 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-500 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
ref={modalRef} ref={modalRef}
style={{
maxHeight: 'calc(100% - env(safe-area-inset-top) * 2)',
}}
> >
{backdrop && ( {backdrop && (
<div className="absolute top-0 left-0 right-0 z-0 h-64 max-h-full w-full"> <div className="absolute top-0 left-0 right-0 z-0 h-64 max-h-full w-full">
@@ -205,11 +213,13 @@ const Modal = ({
)} )}
</div> </div>
)} )}
</div> </Transition>
</Transition.Child> </Transition.Child>,
</div>,
document.body document.body
); );
}; }
);
Modal.displayName = 'Modal';
export default Modal; export default Modal;

View File

@@ -359,12 +359,12 @@ const TvRequestModal = ({
const isOwner = editRequest && editRequest.requestedBy.id === user?.id; const isOwner = editRequest && editRequest.requestedBy.id === user?.id;
return !data?.externalIds.tvdbId && searchModal.show ? ( return data && !data.externalIds.tvdbId && searchModal.show ? (
<SearchByNameModal <SearchByNameModal
tvdbId={tvdbId} tvdbId={tvdbId}
setTvdbId={setTvdbId} setTvdbId={setTvdbId}
closeModal={() => setSearchModal({ show: false })} closeModal={() => setSearchModal({ show: false })}
loading={!data && !error} loading={!error}
onCancel={onCancel} onCancel={onCancel}
modalTitle={intl.formatMessage( modalTitle={intl.formatMessage(
is4k ? messages.request4ktitle : messages.requesttitle, is4k ? messages.request4ktitle : messages.requesttitle,