Skip to content

Commit

Permalink
Merge pull request #225 from Mezzanine-UI/fix/react-utils
Browse files Browse the repository at this point in the history
Fix the bug where scroll lock will cause layout shifting
  • Loading branch information
travor20814 authored Jul 22, 2024
2 parents 3b5060b + 874152d commit 73859d3
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './utils/jsx-types';
export * from './utils/general';
export * from './utils/scroll-lock';
export * from './utils/array-move';
export * from './utils/get-scrollbar-width';

export * from './hooks/useClickAway';
export * from './hooks/useComposeRefs';
Expand Down
27 changes: 27 additions & 0 deletions packages/react/src/utils/get-scrollbar-width.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default function getScrollbarWidth(): number {
// Create a temporary div container and append it into the body
const container = document.createElement('div');

// Append the element into the body
document.body.appendChild(container);

// Force scrollbar on the temporary div element
container.style.overflow = 'scroll';
container.style.width = '100px';
container.style.height = '100px';

// Add a fake inner element to get the scrollbar width
const inner = document.createElement('div');

inner.style.width = '100%';
inner.style.height = '100%';
container.appendChild(inner);

// Calculate the width based on the container width minus its child width
const scrollbarWidth = container.offsetWidth - inner.offsetWidth;

// Remove the temporary elements from the DOM
document.body.removeChild(container);

return scrollbarWidth;
}
10 changes: 8 additions & 2 deletions packages/react/src/utils/scroll-lock.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import getScrollbarWidth from './get-scrollbar-width';

export function lockBodyScroll() {
const {
scrollY,
} = window;

document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;

// Calculate scroll bar width and use padding-right to remain layout width.
const scrollbarWidth = getScrollbarWidth();

document.body.style.paddingRight = `${scrollbarWidth}px`;
document.body.style.overflow = 'hidden';
/** @NOTE workaround for layout breaking (need refactor) */
document.body.style.width = '100vw';
}

export function allowBodyScroll() {
Expand All @@ -16,6 +21,7 @@ export function allowBodyScroll() {
if (document.body.style.position === 'fixed') {
document.body.style.position = '';
document.body.style.top = '';
document.body.style.paddingRight = '';
document.body.style.overflow = '';
window.scrollTo(0, (scrollY || 0) * -1);
}
Expand Down

0 comments on commit 73859d3

Please sign in to comment.