Skip to content

Commit 931a39a

Browse files
committed
feat(RAC): expose --page-width and --visual-viewport-width from Modal
1 parent ef3ff3d commit 931a39a

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

packages/@react-aria/utils/src/useViewportSize.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,20 @@ export function useViewportSize(): ViewportSize {
8888
return size;
8989
}
9090

91+
/**
92+
* Get the viewport size without the scrollbar.
93+
*/
9194
function getViewportSize(): ViewportSize {
9295
return {
9396
// Multiply by the visualViewport scale to get the "natural" size, unaffected by pinch zooming.
94-
width: visualViewport ? visualViewport.width * visualViewport.scale : window.innerWidth,
95-
height: visualViewport ? visualViewport.height * visualViewport.scale : window.innerHeight
97+
width: visualViewport
98+
// The visual viewport width may include the scrollbar gutter. We should use the minimum width between
99+
// the visual viewport and the document element to ensure that the scrollbar width is always excluded.
100+
// See: https://github.com/w3c/csswg-drafts/issues/8099
101+
? Math.min(visualViewport.width * visualViewport.scale, document.documentElement.clientWidth)
102+
: document.documentElement.clientWidth,
103+
height: visualViewport
104+
? visualViewport.height * visualViewport.scale
105+
: document.documentElement.clientHeight
96106
};
97107
}

packages/react-aria-components/src/Modal.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,22 @@ function ModalOverlayInner({UNSTABLE_portalContainer, ...props}: ModalOverlayInn
184184
});
185185

186186
let viewport = useViewportSize();
187+
let pageWidth: number | undefined = undefined;
187188
let pageHeight: number | undefined = undefined;
188189
if (typeof document !== 'undefined') {
189190
let scrollingElement = isScrollable(document.body) ? document.body : document.scrollingElement || document.documentElement;
190-
// Prevent Firefox from adding scrollbars when the page has a fractional height.
191+
// Prevent Firefox from adding scrollbars when the page has a fractional width/height.
192+
let fractionalWidthDifference = scrollingElement.getBoundingClientRect().width % 1;
191193
let fractionalHeightDifference = scrollingElement.getBoundingClientRect().height % 1;
194+
pageWidth = scrollingElement.scrollWidth - fractionalWidthDifference;
192195
pageHeight = scrollingElement.scrollHeight - fractionalHeightDifference;
193196
}
194197

195198
let style = {
196199
...renderProps.style,
200+
'--visual-viewport-width': viewport.width + 'px',
197201
'--visual-viewport-height': viewport.height + 'px',
202+
'--page-width': pageWidth !== undefined ? pageWidth + 'px' : undefined,
198203
'--page-height': pageHeight !== undefined ? pageHeight + 'px' : undefined
199204
};
200205

0 commit comments

Comments
 (0)