Skip to content

Commit 69249f8

Browse files
authored
feat: add optional reserveScrollBarGap (#484)
1 parent 61c3493 commit 69249f8

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

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

+20
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,26 @@ describe('modal', () => {
260260
);
261261
expect(document.body.style.overflow).toBe('');
262262
});
263+
it('should reserve scroll bar gap', () => {
264+
const scrollBarWidth = 42;
265+
const innerWidth = 500;
266+
Object.defineProperty(window, 'innerWidth', {
267+
writable: true,
268+
configurable: true,
269+
value: innerWidth,
270+
});
271+
Object.defineProperty(document.documentElement, 'clientWidth', {
272+
writable: true,
273+
configurable: true,
274+
value: innerWidth - scrollBarWidth,
275+
});
276+
render(
277+
<Modal open={true} onClose={() => null} reserveScrollBarGap={true}>
278+
<div>modal content</div>
279+
</Modal>
280+
);
281+
expect(document.body.style.paddingRight).toBe(`${scrollBarWidth}px`);
282+
});
263283
});
264284

265285
describe('closeIcon', () => {

react-responsive-modal/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@
4747
"size-limit": [
4848
{
4949
"path": "dist/react-responsive-modal.cjs.production.min.js",
50-
"limit": "4.0 KB"
50+
"limit": "4.1 KB"
5151
},
5252
{
5353
"path": "dist/react-responsive-modal.esm.js",
54-
"limit": "4.0 KB"
54+
"limit": "4.1 KB"
5555
}
5656
],
5757
"dependencies": {

react-responsive-modal/src/index.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ export interface ModalProps {
128128
* ARIA description for modal
129129
*/
130130
ariaDescribedby?: string;
131+
/**
132+
* Avoid unpleasant flickering effect when body overflow is hidden. For more information see https://www.npmjs.com/package/body-scroll-lock
133+
*/
134+
reserveScrollBarGap?: boolean;
131135
/**
132136
* id attribute for modal
133137
*/
@@ -179,6 +183,7 @@ export const Modal = React.forwardRef(
179183
onOverlayClick,
180184
onAnimationEnd,
181185
children,
186+
reserveScrollBarGap,
182187
}: ModalProps,
183188
ref: React.ForwardedRef<HTMLDivElement>
184189
) => {
@@ -200,7 +205,7 @@ export const Modal = React.forwardRef(
200205
useModalManager(refModal, open);
201206

202207
// Hook used to manage the scroll
203-
useScrollLock(refModal, open, showPortal, blockScroll);
208+
useScrollLock(refModal, open, showPortal, blockScroll, reserveScrollBarGap);
204209

205210
const handleOpen = () => {
206211
if (

react-responsive-modal/src/useScrollLock.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@ export const useScrollLock = (
55
refModal: React.RefObject<Element>,
66
open: boolean,
77
showPortal: boolean,
8-
blockScroll: boolean
8+
blockScroll: boolean,
9+
reserveScrollBarGap?: boolean
910
) => {
1011
const oldRef = useRef<Element | null>(null);
1112

1213
useEffect(() => {
1314
if (open && refModal.current && blockScroll) {
1415
oldRef.current = refModal.current;
15-
disableBodyScroll(refModal.current);
16+
disableBodyScroll(refModal.current, { reserveScrollBarGap });
1617
}
1718
return () => {
1819
if (oldRef.current) {
1920
enableBodyScroll(oldRef.current);
2021
oldRef.current = null;
2122
}
2223
};
23-
}, [open, showPortal, refModal]);
24+
}, [open, showPortal, refModal, blockScroll, reserveScrollBarGap]);
2425
};

0 commit comments

Comments
 (0)