mirror of
https://github.com/sct/overseerr.git
synced 2025-09-29 13:33:26 +02:00
fix: clicking outside modal closes modal again (#2984)
This commit is contained in:
@@ -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,81 +36,89 @@ interface ModalProps {
|
|||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Modal = ({
|
const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||||
title,
|
(
|
||||||
onCancel,
|
{
|
||||||
onOk,
|
title,
|
||||||
cancelText,
|
onCancel,
|
||||||
okText,
|
onOk,
|
||||||
okDisabled = false,
|
cancelText,
|
||||||
cancelButtonType = 'default',
|
okText,
|
||||||
okButtonType = 'primary',
|
okDisabled = false,
|
||||||
children,
|
cancelButtonType = 'default',
|
||||||
disableScrollLock,
|
okButtonType = 'primary',
|
||||||
backgroundClickable = true,
|
children,
|
||||||
iconSvg,
|
disableScrollLock,
|
||||||
secondaryButtonType = 'default',
|
backgroundClickable = true,
|
||||||
secondaryDisabled = false,
|
iconSvg,
|
||||||
onSecondary,
|
secondaryButtonType = 'default',
|
||||||
secondaryText,
|
secondaryDisabled = false,
|
||||||
tertiaryButtonType = 'default',
|
onSecondary,
|
||||||
tertiaryDisabled = false,
|
secondaryText,
|
||||||
tertiaryText,
|
tertiaryButtonType = 'default',
|
||||||
onTertiary,
|
tertiaryDisabled = false,
|
||||||
backdrop,
|
tertiaryText,
|
||||||
}: ModalProps) => {
|
loading = false,
|
||||||
const intl = useIntl();
|
onTertiary,
|
||||||
const modalRef = useRef<HTMLDivElement>(null);
|
backdrop,
|
||||||
useClickOutside(modalRef, () => {
|
},
|
||||||
typeof onCancel === 'function' && backgroundClickable
|
parentRef
|
||||||
? onCancel()
|
) => {
|
||||||
: undefined;
|
const intl = useIntl();
|
||||||
});
|
const modalRef = useRef<HTMLDivElement>(null);
|
||||||
useLockBodyScroll(true, disableScrollLock);
|
useClickOutside(modalRef, () => {
|
||||||
|
typeof onCancel === 'function' && backgroundClickable
|
||||||
|
? onCancel()
|
||||||
|
: undefined;
|
||||||
|
});
|
||||||
|
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
|
||||||
as={Fragment}
|
appear
|
||||||
enter="transition opacity-0 duration-300 transform scale-75"
|
as="div"
|
||||||
enterFrom="opacity-0 scale-75"
|
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"
|
||||||
enterTo="opacity-100 scale-100"
|
enter="transition opacity-0 duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-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"
|
||||||
|
ref={parentRef}
|
||||||
>
|
>
|
||||||
<div style={{ position: 'absolute' }}>
|
<Transition
|
||||||
<LoadingSpinner />
|
appear
|
||||||
</div>
|
as={Fragment}
|
||||||
</Transition.Child>
|
enter="transition opacity-0 duration-300 transform scale-75"
|
||||||
<Transition.Child
|
enterFrom="opacity-0 scale-75"
|
||||||
as={Fragment}
|
enterTo="opacity-100 scale-100"
|
||||||
enter="transition opacity-0 duration-300 transform scale-75"
|
leave="transition opacity-100 duration-300"
|
||||||
enterFrom="opacity-0 scale-75"
|
leaveFrom="opacity-100"
|
||||||
enterTo="opacity-100 scale-100"
|
leaveTo="opacity-0"
|
||||||
leave="transition opacity-100 duration-300"
|
show={loading}
|
||||||
leaveFrom="opacity-100"
|
>
|
||||||
leaveTo="opacity-0"
|
<div style={{ position: 'absolute' }}>
|
||||||
>
|
<LoadingSpinner />
|
||||||
<div
|
</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"
|
</Transition>
|
||||||
|
<Transition
|
||||||
|
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"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline"
|
aria-labelledby="modal-headline"
|
||||||
ref={modalRef}
|
|
||||||
style={{
|
style={{
|
||||||
maxHeight: 'calc(100% - env(safe-area-inset-top) * 2)',
|
maxHeight: 'calc(100% - env(safe-area-inset-top) * 2)',
|
||||||
}}
|
}}
|
||||||
|
appear
|
||||||
|
as="div"
|
||||||
|
enter="transition opacity-0 duration-300 transform scale-75"
|
||||||
|
enterFrom="opacity-0 scale-75"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="transition opacity-100 duration-300"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
show={!loading}
|
||||||
|
ref={modalRef}
|
||||||
>
|
>
|
||||||
{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;
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user