Skip to content

Commit

Permalink
[@mantine/core] Modal: Fix incorrect click outside behavior (#2896)
Browse files Browse the repository at this point in the history
  • Loading branch information
Keilo75 committed Nov 12, 2022
1 parent fa44806 commit 17f8aa5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
12 changes: 12 additions & 0 deletions src/mantine-core/src/Modal/Modal.story.tsx
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { Modal } from './Modal';
import { Button } from '../Button';
import { ColorInput } from '../ColorInput';

export default { title: 'Modal' };

Expand Down Expand Up @@ -52,3 +53,14 @@ export function WithPageScrollbars() {
</div>
);
}

export function WithPortalChildren() {
return (
<div style={{ padding: 40 }}>
<WrappedModal>
<ColorInput label="No Portal" mb="md" />
<ColorInput label="Within Portal" mb="md" withinPortal />
</WrappedModal>
</div>
);
}
29 changes: 25 additions & 4 deletions src/mantine-core/src/Modal/Modal.tsx
@@ -1,5 +1,12 @@
import React, { useEffect } from 'react';
import { useScrollLock, useFocusTrap, useFocusReturn, useId } from '@mantine/hooks';
import React, { useEffect, useRef } from 'react';
import {
useScrollLock,
useFocusTrap,
useFocusReturn,
useId,
useWindowEvent,
useMergedRef,
} from '@mantine/hooks';
import {
DefaultProps,
MantineNumberSize,
Expand Down Expand Up @@ -171,6 +178,9 @@ export function Modal(props: ModalProps) {
{ unstyled, classNames, styles, name: 'Modal' }
);
const focusTrapRef = useFocusTrap(trapFocus && opened);
const overlayRef = useRef<HTMLDivElement>(null);
const mergedRef = useMergedRef(focusTrapRef, overlayRef);

const _overlayOpacity =
typeof overlayOpacity === 'number'
? overlayOpacity
Expand All @@ -197,6 +207,17 @@ export function Modal(props: ModalProps) {

useFocusReturn({ opened, shouldReturnFocus: trapFocus && withFocusReturn });

const clickTarget = useRef<EventTarget>(null);
useWindowEvent('mousedown', (e) => {
clickTarget.current = e.target;
});

const handleOutsideClick = () => {
if (clickTarget.current !== overlayRef.current) return;

closeOnClickOutside && onClose();
};

return (
<OptionalPortal withinPortal={withinPortal} target={target}>
<GroupedTransition
Expand Down Expand Up @@ -236,13 +257,13 @@ export function Modal(props: ModalProps) {
<div
role="presentation"
className={classes.inner}
onClick={() => closeOnClickOutside && onClose()}
onClick={handleOutsideClick}
onKeyDown={(event) => {
const shouldTrigger =
(event.target as any)?.getAttribute('data-mantine-stop-propagation') !== 'true';
shouldTrigger && event.key === 'Escape' && closeOnEscape && onClose();
}}
ref={focusTrapRef}
ref={mergedRef}
>
<Paper<'div'>
className={classes.modal}
Expand Down

0 comments on commit 17f8aa5

Please sign in to comment.