Skip to content

Commit fde2a81

Browse files
feat(RAC): expose --page-width and --visual-viewport-width from Modal (adobe#9318)
Co-authored-by: Devon Govett <devongovett@gmail.com>
1 parent 233900c commit fde2a81

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
@@ -94,10 +94,20 @@ export function useViewportSize(): ViewportSize {
9494
return size;
9595
}
9696

97+
/**
98+
* Get the viewport size without the scrollbar.
99+
*/
97100
function getViewportSize(): ViewportSize {
98101
return {
99102
// Multiply by the visualViewport scale to get the "natural" size, unaffected by pinch zooming.
100-
width: visualViewport ? visualViewport.width * visualViewport.scale : document.documentElement.clientWidth,
101-
height: visualViewport ? visualViewport.height * visualViewport.scale : document.documentElement.clientHeight
103+
width: visualViewport
104+
// The visual viewport width may include the scrollbar gutter. We should use the minimum width between
105+
// the visual viewport and the document element to ensure that the scrollbar width is always excluded.
106+
// See: https://github.com/w3c/csswg-drafts/issues/8099
107+
? Math.min(visualViewport.width * visualViewport.scale, document.documentElement.clientWidth)
108+
: document.documentElement.clientWidth,
109+
height: visualViewport
110+
? visualViewport.height * visualViewport.scale
111+
: document.documentElement.clientHeight
102112
};
103113
}

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

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

187187
let viewport = useViewportSize();
188+
let pageWidth: number | undefined = undefined;
188189
let pageHeight: number | undefined = undefined;
189190
if (typeof document !== 'undefined') {
190191
let scrollingElement = isScrollable(document.body) ? document.body : document.scrollingElement || document.documentElement;
191-
// Prevent Firefox from adding scrollbars when the page has a fractional height.
192+
// Prevent Firefox from adding scrollbars when the page has a fractional width/height.
193+
let fractionalWidthDifference = scrollingElement.getBoundingClientRect().width % 1;
192194
let fractionalHeightDifference = scrollingElement.getBoundingClientRect().height % 1;
195+
pageWidth = scrollingElement.scrollWidth - fractionalWidthDifference;
193196
pageHeight = scrollingElement.scrollHeight - fractionalHeightDifference;
194197
}
195198

196199
let style = {
197200
...renderProps.style,
201+
'--visual-viewport-width': viewport.width + 'px',
198202
'--visual-viewport-height': viewport.height + 'px',
203+
'--page-width': pageWidth !== undefined ? pageWidth + 'px' : undefined,
199204
'--page-height': pageHeight !== undefined ? pageHeight + 'px' : undefined
200205
};
201206

0 commit comments

Comments
 (0)