Skip to content

Commit 5727913

Browse files
authored
fix!: fix rendering issues in Safari, Firefox by changing the structure
1 parent b016ec4 commit 5727913

File tree

7 files changed

+201
-112
lines changed

7 files changed

+201
-112
lines changed

react-responsive-modal/__tests__/index.test.tsx

+15-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('modal', () => {
1212
</Modal>
1313
);
1414

15-
fireEvent.click(getByTestId('overlay'));
15+
fireEvent.click(getByTestId('modal-container'));
1616
expect(onClose).toHaveBeenCalledTimes(1);
1717
});
1818

@@ -24,7 +24,7 @@ describe('modal', () => {
2424
</Modal>
2525
);
2626

27-
fireEvent.click(getByTestId('overlay'));
27+
fireEvent.click(getByTestId('modal-container'));
2828
expect(onClose).not.toHaveBeenCalled();
2929
});
3030

@@ -147,7 +147,7 @@ describe('modal', () => {
147147
</Modal>
148148
);
149149
// Simulate the browser animation end
150-
fireEvent.animationEnd(getByTestId('overlay'));
150+
fireEvent.animationEnd(getByTestId('modal'));
151151
await waitFor(
152152
() => {
153153
expect(queryByTestId('modal')).not.toBeInTheDocument();
@@ -195,7 +195,7 @@ describe('modal', () => {
195195
</React.Fragment>
196196
);
197197

198-
fireEvent.animationEnd(getAllByTestId('overlay')[1]);
198+
fireEvent.animationEnd(getAllByTestId('modal')[1]);
199199
await waitFor(
200200
() => {
201201
expect(queryByText(/second modal/)).not.toBeInTheDocument();
@@ -216,7 +216,7 @@ describe('modal', () => {
216216
</React.Fragment>
217217
);
218218

219-
fireEvent.animationEnd(getAllByTestId('overlay')[0]);
219+
fireEvent.animationEnd(getAllByTestId('modal')[0]);
220220
await waitFor(
221221
() => {
222222
expect(queryByText(/first modal/)).not.toBeInTheDocument();
@@ -251,7 +251,7 @@ describe('modal', () => {
251251
</React.Fragment>
252252
);
253253

254-
fireEvent.animationEnd(getAllByTestId('overlay')[1]);
254+
fireEvent.animationEnd(getAllByTestId('modal')[1]);
255255
await waitFor(
256256
() => {
257257
expect(queryByText(/second modal/)).not.toBeInTheDocument();
@@ -344,7 +344,7 @@ describe('modal', () => {
344344
<div>modal content</div>
345345
</Modal>
346346
);
347-
fireEvent.animationEnd(getByTestId('overlay'));
347+
fireEvent.animationEnd(getByTestId('modal'));
348348
expect(queryByTestId('modal')).toBeNull();
349349
});
350350
});
@@ -357,10 +357,10 @@ describe('modal', () => {
357357
</Modal>
358358
);
359359

360-
expect(getByTestId('modal').classList.length).toBe(1);
360+
expect(getByTestId('modal-container').classList.length).toBe(1);
361361
expect(
362-
getByTestId('modal').classList.contains(
363-
'react-responsive-modal-modalCenter'
362+
getByTestId('modal-container').classList.contains(
363+
'react-responsive-modal-containerCenter'
364364
)
365365
).toBeFalsy();
366366
});
@@ -372,10 +372,10 @@ describe('modal', () => {
372372
</Modal>
373373
);
374374

375-
expect(getByTestId('modal').classList.length).toBe(2);
375+
expect(getByTestId('modal-container').classList.length).toBe(2);
376376
expect(
377-
getByTestId('modal').classList.contains(
378-
'react-responsive-modal-modalCenter'
377+
getByTestId('modal-container').classList.contains(
378+
'react-responsive-modal-containerCenter'
379379
)
380380
).toBeTruthy();
381381
});
@@ -464,7 +464,7 @@ describe('modal', () => {
464464
</Modal>
465465
);
466466

467-
fireEvent.click(getByTestId('overlay'));
467+
fireEvent.click(getByTestId('modal-container'));
468468
expect(onOverlayClick).toHaveBeenCalledTimes(1);
469469
});
470470
});
@@ -478,7 +478,7 @@ describe('modal', () => {
478478
</Modal>
479479
);
480480

481-
fireEvent.animationEnd(getByTestId('overlay'));
481+
fireEvent.animationEnd(getByTestId('modal'));
482482
expect(onAnimationEnd).toHaveBeenCalledTimes(1);
483483
});
484484
});

react-responsive-modal/src/CloseIcon.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface CloseIconProps {
1515
classes: {
1616
closeButton?: string;
1717
};
18-
onClickCloseIcon: () => void;
18+
onClick: () => void;
1919
}
2020

2121
const CloseIcon = ({
@@ -24,13 +24,13 @@ const CloseIcon = ({
2424
styles,
2525
id,
2626
closeIcon,
27-
onClickCloseIcon,
27+
onClick,
2828
}: CloseIconProps) => (
2929
<button
3030
id={id}
3131
className={cx(classes.closeButton, classNames?.closeButton)}
3232
style={styles?.closeButton}
33-
onClick={onClickCloseIcon}
33+
onClick={onClick}
3434
data-testid="close-button"
3535
>
3636
{closeIcon ? (

react-responsive-modal/src/index.tsx

+75-48
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ import { modalManager, useModalManager } from './modalManager';
77
import { isBrowser, blockNoScroll, unblockNoScroll } from './utils';
88

99
const classes = {
10+
root: 'react-responsive-modal-root',
1011
overlay: 'react-responsive-modal-overlay',
12+
overlayAnimationIn: 'react-responsive-modal-overlay-in',
13+
overlayAnimationOut: 'react-responsive-modal-overlay-out',
14+
modalContainer: 'react-responsive-modal-container',
15+
modalContainerCenter: 'react-responsive-modal-containerCenter',
1116
modal: 'react-responsive-modal-modal',
12-
modalCenter: 'react-responsive-modal-modalCenter',
17+
modalAnimationIn: 'react-responsive-modal-modal-in',
18+
modalAnimationOut: 'react-responsive-modal-modal-out',
1319
closeButton: 'react-responsive-modal-closeButton',
14-
animationIn: 'react-responsive-modal-fadeIn',
15-
animationOut: 'react-responsive-modal-fadeOut',
1620
};
1721

1822
export interface ModalProps {
@@ -74,18 +78,24 @@ export interface ModalProps {
7478
* An object containing classNames to style the modal.
7579
*/
7680
classNames?: {
81+
root?: string;
7782
overlay?: string;
83+
overlayAnimationIn?: string;
84+
overlayAnimationOut?: string;
85+
modalContainer?: string;
7886
modal?: string;
87+
modalAnimationIn?: string;
88+
modalAnimationOut?: string;
7989
closeButton?: string;
8090
closeIcon?: string;
81-
animationIn?: string;
82-
animationOut?: string;
8391
};
8492
/**
8593
* An object containing the styles objects to style the modal.
8694
*/
8795
styles?: {
96+
root?: React.CSSProperties;
8897
overlay?: React.CSSProperties;
98+
modalContainer?: React.CSSProperties;
8999
modal?: React.CSSProperties;
90100
closeButton?: React.CSSProperties;
91101
closeIcon?: React.CSSProperties;
@@ -146,7 +156,7 @@ export const Modal = ({
146156
closeIconId,
147157
closeIcon,
148158
focusTrapped = true,
149-
animationDuration = 500,
159+
animationDuration = 300,
150160
classNames,
151161
styles,
152162
role = 'dialog',
@@ -179,6 +189,7 @@ export const Modal = ({
179189
if (blockScroll) {
180190
blockNoScroll();
181191
}
192+
182193
if (
183194
refContainer.current &&
184195
!container &&
@@ -198,6 +209,7 @@ export const Modal = ({
198209
) {
199210
unblockNoScroll();
200211
}
212+
201213
if (
202214
refContainer.current &&
203215
!container &&
@@ -264,10 +276,6 @@ export const Modal = ({
264276
refShouldClose.current = false;
265277
};
266278

267-
const handleClickCloseIcon = () => {
268-
onClose();
269-
};
270-
271279
const handleAnimationEnd = () => {
272280
if (!open) {
273281
setShowPortal(false);
@@ -278,52 +286,71 @@ export const Modal = ({
278286

279287
const containerModal = container || refContainer.current;
280288

289+
const overlayAnimation = open
290+
? classNames?.overlayAnimationIn ?? classes.overlayAnimationIn
291+
: classNames?.overlayAnimationOut ?? classes.overlayAnimationOut;
292+
293+
const modalAnimation = open
294+
? classNames?.modalAnimationIn ?? classes.modalAnimationIn
295+
: classNames?.modalAnimationOut ?? classes.modalAnimationOut;
296+
281297
return showPortal && containerModal
282298
? ReactDom.createPortal(
283299
<div
284-
style={{
285-
animation: `${
286-
open
287-
? classNames?.animationIn ?? classes.animationIn
288-
: classNames?.animationOut ?? classes.animationOut
289-
} ${animationDuration}ms`,
290-
...styles?.overlay,
291-
}}
292-
className={cx(classes.overlay, classNames?.overlay)}
293-
onClick={handleClickOverlay}
294-
onAnimationEnd={handleAnimationEnd}
295-
data-testid="overlay"
300+
className={cx(classes.root, classNames?.root)}
301+
style={styles?.root}
302+
data-testid="root"
296303
>
297304
<div
298-
ref={refModal}
305+
className={cx(classes.overlay, classNames?.overlay)}
306+
data-testid="overlay"
307+
aria-hidden={true}
308+
style={{
309+
animation: `${overlayAnimation} ${animationDuration}ms`,
310+
...styles?.overlay,
311+
}}
312+
/>
313+
<div
299314
className={cx(
300-
classes.modal,
301-
center && classes.modalCenter,
302-
classNames?.modal
315+
classes.modalContainer,
316+
center && classes.modalContainerCenter,
317+
classNames?.modalContainer
303318
)}
304-
style={styles?.modal}
305-
onMouseDown={handleModalEvent}
306-
onMouseUp={handleModalEvent}
307-
onClick={handleModalEvent}
308-
id={modalId}
309-
role={role}
310-
aria-modal="true"
311-
aria-labelledby={ariaLabelledby}
312-
aria-describedby={ariaDescribedby}
313-
data-testid="modal"
319+
style={styles?.modalContainer}
320+
data-testid="modal-container"
321+
onClick={handleClickOverlay}
314322
>
315-
{focusTrapped && <FocusTrap container={refModal} />}
316-
{children}
317-
{showCloseIcon && (
318-
<CloseIcon
319-
classes={classes}
320-
classNames={classNames}
321-
styles={styles}
322-
closeIcon={closeIcon}
323-
onClickCloseIcon={handleClickCloseIcon}
324-
id={closeIconId}
325-
/>
326-
)}
323+
<div
324+
ref={refModal}
325+
className={cx(classes.modal, classNames?.modal)}
326+
style={{
327+
animation: `${modalAnimation} ${animationDuration}ms`,
328+
...styles?.modal,
329+
}}
330+
onMouseDown={handleModalEvent}
331+
onMouseUp={handleModalEvent}
332+
onClick={handleModalEvent}
333+
onAnimationEnd={handleAnimationEnd}
334+
id={modalId}
335+
role={role}
336+
aria-modal="true"
337+
aria-labelledby={ariaLabelledby}
338+
aria-describedby={ariaDescribedby}
339+
data-testid="modal"
340+
>
341+
{focusTrapped && <FocusTrap container={refModal} />}
342+
{children}
343+
{showCloseIcon && (
344+
<CloseIcon
345+
classes={classes}
346+
classNames={classNames}
347+
styles={styles}
348+
closeIcon={closeIcon}
349+
onClick={onClose}
350+
id={closeIconId}
351+
/>
352+
)}
353+
</div>
327354
</div>
328355
</div>,
329356
containerModal

0 commit comments

Comments
 (0)