Skip to content

Commit e4f8393

Browse files
committed
fix: body scroll when open modal #1472
1 parent c86a261 commit e4f8393

File tree

5 files changed

+56
-66
lines changed

5 files changed

+56
-66
lines changed

components/modal/__tests__/__snapshots__/Modal.test.js.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`Modal render correctly 1`] = `
44
<div>
55
<div>
66
<div>
7-
<div>
7+
<div class="ant-modal-root">
88
<div class="ant-modal-mask"></div>
99
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
1010
<div role="document" class="ant-modal" style="width: 520px;">
@@ -29,7 +29,7 @@ exports[`Modal render correctly 2`] = `
2929
<div>
3030
<div>
3131
<div>
32-
<div>
32+
<div class="ant-modal-root">
3333
<div class="ant-modal-mask"></div>
3434
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
3535
<div role="document" class="ant-modal" style="width: 520px;">
@@ -54,7 +54,7 @@ exports[`Modal render without footer 1`] = `
5454
<div>
5555
<div>
5656
<div>
57-
<div>
57+
<div class="ant-modal-root">
5858
<div class="ant-modal-mask"></div>
5959
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
6060
<div role="document" class="ant-modal" style="width: 520px;">

components/vc-dialog/Dialog.jsx

+48-62
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ function offset(el) {
4646
return pos;
4747
}
4848

49+
let cacheOverflow = {};
50+
4951
export default {
5052
mixins: [BaseMixin],
5153
props: initDefaultProps(IDialogPropTypes, {
@@ -57,6 +59,7 @@ export default {
5759
destroyOnClose: false,
5860
prefixCls: 'rc-dialog',
5961
getOpenCount: () => null,
62+
focusTriggerAfterClose: true,
6063
}),
6164
data() {
6265
return {
@@ -81,16 +84,6 @@ export default {
8184
},
8285
},
8386

84-
// private inTransition: boolean;
85-
// private titleId: string;
86-
// private openTime: number;
87-
// private lastOutSideFocusNode: HTMLElement | null;
88-
// private wrap: HTMLElement;
89-
// private dialog: any;
90-
// private sentinel: HTMLElement;
91-
// private bodyIsOverflowing: boolean;
92-
// private scrollbarWidth: number;
93-
9487
beforeMount() {
9588
this.inTransition = false;
9689
this.titleId = `rcDialogTitle${uuid++}`;
@@ -107,7 +100,7 @@ export default {
107100
beforeDestroy() {
108101
const { visible, getOpenCount } = this;
109102
if ((visible || this.inTransition) && !getOpenCount()) {
110-
this.removeScrollingEffect();
103+
this.switchScrollingEffect();
111104
}
112105
clearTimeout(this.timeoutId);
113106
},
@@ -118,12 +111,13 @@ export default {
118111
},
119112
updatedCallback(visible) {
120113
const mousePosition = this.mousePosition;
114+
const {mask, focusTriggerAfterClose} = this;
121115
if (this.visible) {
122116
// first show
123117
if (!visible) {
124118
this.openTime = Date.now();
125119
// this.lastOutSideFocusNode = document.activeElement
126-
this.addScrollingEffect();
120+
this.switchScrollingEffect();
127121
// this.$refs.wrap.focus()
128122
this.tryFocus();
129123
const dialogNode = this.$refs.dialog.$el;
@@ -139,7 +133,7 @@ export default {
139133
}
140134
} else if (visible) {
141135
this.inTransition = true;
142-
if (this.mask && this.lastOutSideFocusNode) {
136+
if (mask && this.lastOutSideFocusNode && focusTriggerAfterClose) {
143137
try {
144138
this.lastOutSideFocusNode.focus();
145139
} catch (e) {
@@ -166,7 +160,7 @@ export default {
166160
this.destroyPopup = true;
167161
}
168162
this.inTransition = false;
169-
this.removeScrollingEffect();
163+
this.switchScrollingEffect();
170164
if (afterClose) {
171165
afterClose();
172166
}
@@ -224,6 +218,7 @@ export default {
224218
bodyStyle,
225219
visible,
226220
bodyProps,
221+
forceRender,
227222
} = this;
228223
const dest = {};
229224
if (width !== undefined) {
@@ -284,6 +279,7 @@ export default {
284279
ref="dialog"
285280
style={style}
286281
class={cls}
282+
forceRender={forceRender}
287283
onMousedown={this.onDialogMouseDown}
288284
>
289285
<div tabIndex={0} ref="sentinelStart" style={sentinelStyle} aria-hidden="true" />
@@ -369,60 +365,50 @@ export default {
369365
// document.body.style.paddingRight = `${this.scrollbarWidth}px`;
370366
// }
371367
// },
372-
addScrollingEffect() {
368+
switchScrollingEffect() {
373369
const { getOpenCount } = this;
374370
const openCount = getOpenCount();
375-
if (openCount !== 1) {
376-
return;
377-
}
378-
switchScrollingEffect();
379-
document.body.style.overflow = 'hidden';
380-
},
381-
removeScrollingEffect() {
382-
const { getOpenCount } = this;
383-
const openCount = getOpenCount();
384-
if (openCount !== 0) {
385-
return;
371+
if (openCount === 1) {
372+
if (cacheOverflow.hasOwnProperty('overflowX')) {
373+
return;
374+
}
375+
cacheOverflow = {
376+
overflowX: document.body.style.overflowX,
377+
overflowY: document.body.style.overflowY,
378+
overflow: document.body.style.overflow,
379+
};
380+
switchScrollingEffect();
381+
// Must be set after switchScrollingEffect
382+
document.body.style.overflow = 'hidden';
383+
} else if (!openCount) {
384+
// IE browser doesn't merge overflow style, need to set it separately
385+
// https://github.com/ant-design/ant-design/issues/19393
386+
if (cacheOverflow.overflow !== undefined) {
387+
document.body.style.overflow = cacheOverflow.overflow;
388+
}
389+
if (cacheOverflow.overflowX !== undefined) {
390+
document.body.style.overflowX = cacheOverflow.overflowX;
391+
}
392+
if (cacheOverflow.overflowY !== undefined) {
393+
document.body.style.overflowY = cacheOverflow.overflowY;
394+
}
395+
cacheOverflow = {};
396+
switchScrollingEffect(true);
386397
}
387-
document.body.style.overflow = '';
388-
switchScrollingEffect(true);
389-
// this.resetAdjustments();
390398
},
399+
// removeScrollingEffect() {
400+
// const { getOpenCount } = this;
401+
// const openCount = getOpenCount();
402+
// if (openCount !== 0) {
403+
// return;
404+
// }
405+
// document.body.style.overflow = '';
406+
// switchScrollingEffect(true);
407+
// // this.resetAdjustments();
408+
// },
391409
close(e) {
392410
this.__emit('close', e);
393411
},
394-
// checkScrollbar() {
395-
// let fullWindowWidth = window.innerWidth;
396-
// if (!fullWindowWidth) {
397-
// // workaround for missing window.innerWidth in IE8
398-
// const documentElementRect = document.documentElement.getBoundingClientRect();
399-
// fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
400-
// }
401-
// this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
402-
// if (this.bodyIsOverflowing) {
403-
// this.scrollbarWidth = getScrollBarSize();
404-
// }
405-
// },
406-
// resetScrollbar() {
407-
// document.body.style.paddingRight = '';
408-
// },
409-
// adjustDialog() {
410-
// if (this.$refs.wrap && this.scrollbarWidth !== undefined) {
411-
// const modalIsOverflowing =
412-
// this.$refs.wrap.scrollHeight > document.documentElement.clientHeight;
413-
// this.$refs.wrap.style.paddingLeft = `${
414-
// !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : ''
415-
// }px`;
416-
// this.$refs.wrap.style.paddingRight = `${
417-
// this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
418-
// }px`;
419-
// }
420-
// },
421-
// resetAdjustments() {
422-
// if (this.$refs.wrap) {
423-
// this.$refs.wrap.style.paddingLeft = this.$refs.wrap.style.paddingLeft = '';
424-
// }
425-
// },
426412
},
427413
render() {
428414
const { prefixCls, maskClosable, visible, wrapClassName, title, wrapProps } = this;
@@ -433,7 +419,7 @@ export default {
433419
style.display = null;
434420
}
435421
return (
436-
<div>
422+
<div class={`${prefixCls}-root`}>
437423
{this.getMaskElement()}
438424
<div
439425
tabIndex={-1}

components/vc-dialog/IDialogPropTypes.js

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ function IDialogPropTypes() {
3737
closeIcon: PropTypes.any,
3838
forceRender: PropTypes.bool,
3939
getOpenCount: PropTypes.func,
40+
// https://github.com/ant-design/ant-design/issues/19771
41+
// https://github.com/react-component/dialog/issues/95
42+
focusTriggerAfterClose: PropTypes.bool,
4043
};
4144
}
4245

components/vc-dialog/LazyRenderBox.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from '../_util/vue-types';
33
const ILazyRenderBoxPropTypes = {
44
visible: PropTypes.bool,
55
hiddenClassName: PropTypes.string,
6+
forceRender: PropTypes.bool,
67
};
78

89
export default {

components/vc-dialog/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
// based on vc-dialog 7.5.5
1+
// based on vc-dialog 7.5.14
22
import DialogWrap from './DialogWrap';
33
export default DialogWrap;

0 commit comments

Comments
 (0)