Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OV-326: Close Menu Body when click outside, but also when click out… #334

Merged
9 changes: 7 additions & 2 deletions frontend/src/bundles/chat/pages/chat-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import {
type Properties = {
isChatOpen: boolean;
onModalChatClose: () => void;
modalReference: React.RefObject<HTMLDivElement>;
};

const ChatModal: React.FC<Properties> = ({ isChatOpen, onModalChatClose }) => {
const ChatModal: React.FC<Properties> = ({
isChatOpen,
onModalChatClose,
modalReference,
}) => {
const dispatch = useAppDispatch();
const { messages } = useAppSelector(({ chat }) => ({
messages: chat.messages,
Expand All @@ -42,7 +47,7 @@ const ChatModal: React.FC<Properties> = ({ isChatOpen, onModalChatClose }) => {
size="5xl"
>
<ModalOverlay />
<ModalContent borderRadius="xl">
<ModalContent borderRadius="xl" ref={modalReference}>
<ModalCloseButton color="white" />
<Chat
messages={messages}
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/bundles/common/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ import { type ModalProps } from '~/bundles/common/types/types.js';

import styles from './styles.module.css';

const Modal: React.FC<ModalProps> = ({ children, ...properties }) => {
type Properties = {
modalReference?: React.RefObject<HTMLElement>;
} & ModalProps;
const Modal: React.FC<Properties> = ({
children,
modalReference,
...properties
}) => {
return (
<LibraryModal {...properties} isCentered>
<ModalOverlay />
<ModalContent className={styles['modal-content']}>
<ModalContent
className={styles['modal-content']}
ref={modalReference}
>
<ModalCloseButton margin="20px" zIndex={10} />
<ModalBody padding={0}>{children}</ModalBody>
</ModalContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ type Properties = {
title: string | React.ReactNode;
onClose: () => void;
onChatOpen?: () => void;
menuBodyReference: React.RefObject<HTMLDivElement>;
};

const MenuBody: React.FC<React.PropsWithChildren<Properties>> = ({
title,
children,
onClose,
onChatOpen,
menuBodyReference,
}) => {
const menuReference = useRef<HTMLDivElement | null>(null);

Expand All @@ -48,7 +50,7 @@ const MenuBody: React.FC<React.PropsWithChildren<Properties>> = ({

return (
<Box
ref={menuReference}
ref={menuBodyReference}
bg="background.900"
className={styles['menu-body']}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,21 @@ type Properties = {
isOpen: boolean;
onClose: () => void;
scriptId: string | null;
modalReference: React.RefObject<HTMLDivElement>;
};
const VoicesModal: React.FC<Properties> = ({ isOpen, onClose, scriptId }) => {
const VoicesModal: React.FC<Properties> = ({
isOpen,
onClose,
scriptId,
modalReference,
}) => {
return (
<Modal isOpen={isOpen} onClose={onClose} scrollBehavior="inside">
<Modal
isOpen={isOpen}
onClose={onClose}
modalReference={modalReference}
scrollBehavior="inside"
>
{scriptId && (
<VoicesModalContent
scriptId={scriptId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import { actions as studioActions } from '~/bundles/studio/store/studio.js';

import { Script, VoicesModal } from './components/components.js';

const ScriptContent: React.FC = () => {
type Properties = {
modalReference: React.RefObject<HTMLDivElement>;
};
const ScriptContent: React.FC<Properties> = ({ modalReference }) => {
const dispatch = useAppDispatch();
const { dataStatus, scripts, voices } = useAppSelector(
({ studio }) => studio,
Expand Down Expand Up @@ -86,6 +89,7 @@ const ScriptContent: React.FC = () => {
isOpen={Boolean(changeVoiceScriptId)}
onClose={handleCloseVoicesModal}
scriptId={changeVoiceScriptId}
modalReference={modalReference}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ChatModal } from '~/bundles/chat/pages/chat-modal.js';
import { Icon } from '~/bundles/common/components/components.js';
import { DOMEvent } from '~/bundles/common/enums/enums.js';
import {
useAppDispatch,
useAppSelector,
useCallback,
useEffect,
useRef,
useState,
} from '~/bundles/common/hooks/hooks.js';
import { IconName } from '~/bundles/common/icons/icons.js';
Expand All @@ -29,6 +31,8 @@ const VideoMenu: React.FC = () => {

const dispatch = useAppDispatch();
const [isChatOpen, setIsChatOpen] = useState(false);
const modalReference = useRef<HTMLDivElement | null>(null);
const menuBodyReference = useRef<HTMLDivElement | null>(null);

const setActiveItem = useCallback(
(item: ValueOf<typeof MenuItems> | null): void => {
Expand Down Expand Up @@ -74,7 +78,7 @@ const VideoMenu: React.FC = () => {
script: {
label: 'Script',
icon: <Icon as={IconName.SCRIPT} />,
getContent: () => <ScriptContent />,
getContent: () => <ScriptContent modalReference={modalReference} />,
},
// text: {
// label: 'Text',
Expand All @@ -90,6 +94,30 @@ const VideoMenu: React.FC = () => {

const activeMenuItem = activeItem && menuItems[activeItem];

useEffect(() => {
const handleClickOutside = (event: MouseEvent): void => {
const isInsideMenuBody = menuBodyReference.current?.contains(
event.target as Node,
);
const isInsideModal = modalReference.current?.contains(
event.target as Node,
);

if (!isInsideMenuBody && !isInsideModal) {
handleMenuClose();
}
};

document.addEventListener(DOMEvent.MOUSE_DOWN, handleClickOutside);

return () => {
document.removeEventListener(
DOMEvent.MOUSE_DOWN,
handleClickOutside,
);
};
}, [handleMenuClose, menuBodyReference, modalReference]);

return (
<>
<Menu
Expand All @@ -102,13 +130,15 @@ const VideoMenu: React.FC = () => {
title={activeMenuItem.label}
onClose={handleMenuClose}
onChatOpen={handleChatOpen}
menuBodyReference={menuBodyReference}
>
{activeMenuItem.getContent()}
</MenuBody>
)}
<ChatModal
isChatOpen={isChatOpen}
onModalChatClose={handleChatClose}
modalReference={modalReference}
/>
</>
);
Expand Down
Loading