Skip to content

Commit f61730a

Browse files
crisbetommalerba
authored andcommitted
fix(overlay): incorrectly calculating position when page is scrolled horizontally and overlay is anchored to the right (#16235)
Fixes the flexible connected position strategy calculating where to position the panel incorrectly if it's anchored so that its content flows to the left and the page is scrolled horizontally. Furthermore, the calculations for the bounding box width weren't correct for this case either. Fixes #16009.
1 parent 0bfcb32 commit f61730a

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts

+76
Original file line numberDiff line numberDiff line change
@@ -1927,6 +1927,82 @@ describe('FlexibleConnectedPositionStrategy', () => {
19271927
expect(Math.floor(overlayRect.bottom)).toBe(Math.floor(originRect.bottom));
19281928
});
19291929

1930+
it('should position an overlay that is flowing to the left correctly on a page that is ' +
1931+
'scrolled horizontally', () => {
1932+
const veryLargeElement: HTMLElement = document.createElement('div');
1933+
veryLargeElement.style.width = '4000px';
1934+
veryLargeElement.style.height = '4000px';
1935+
document.body.appendChild(veryLargeElement);
1936+
window.scroll(2100, 0);
1937+
1938+
originElement.style.position = 'absolute';
1939+
originElement.style.top = '100px';
1940+
originElement.style.left = '300px';
1941+
1942+
positionStrategy
1943+
.withFlexibleDimensions()
1944+
.withPush(false)
1945+
.withPositions([{
1946+
overlayY: 'top',
1947+
overlayX: 'end',
1948+
originY: 'top',
1949+
originX: 'end'
1950+
}]);
1951+
1952+
attachOverlay({positionStrategy});
1953+
1954+
const originRect = originElement.getBoundingClientRect();
1955+
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
1956+
1957+
expect(Math.floor(overlayRect.right)).toBe(Math.floor(originRect.right));
1958+
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top));
1959+
1960+
window.scroll(0, 0);
1961+
document.body.removeChild(veryLargeElement);
1962+
});
1963+
1964+
it('should size the bounding box that is flowing to the left correctly on a page that is ' +
1965+
'scrolled horizontally', () => {
1966+
const veryLargeElement: HTMLElement = document.createElement('div');
1967+
veryLargeElement.style.width = '4000px';
1968+
veryLargeElement.style.height = '4000px';
1969+
document.body.appendChild(veryLargeElement);
1970+
window.scroll(100, 0);
1971+
1972+
originElement.style.position = 'absolute';
1973+
originElement.style.top = '100px';
1974+
originElement.style.left = '300px';
1975+
1976+
positionStrategy
1977+
.withFlexibleDimensions()
1978+
.withPush(false)
1979+
.withPositions([{
1980+
overlayY: 'top',
1981+
overlayX: 'end',
1982+
originY: 'top',
1983+
originX: 'end'
1984+
}]);
1985+
1986+
attachOverlay({positionStrategy});
1987+
1988+
let originRect = originElement.getBoundingClientRect();
1989+
let boundingBoxRect = overlayRef.hostElement.getBoundingClientRect();
1990+
1991+
expect(Math.floor(originRect.right)).toBe(Math.floor(boundingBoxRect.width));
1992+
1993+
window.scroll(200, 0);
1994+
overlayRef.updatePosition();
1995+
1996+
originRect = originElement.getBoundingClientRect();
1997+
boundingBoxRect = overlayRef.hostElement.getBoundingClientRect();
1998+
1999+
expect(Math.floor(originRect.right)).toBe(Math.floor(boundingBoxRect.width));
2000+
2001+
window.scroll(0, 0);
2002+
document.body.removeChild(veryLargeElement);
2003+
});
2004+
2005+
19302006
});
19312007

19322008
describe('onPositionChange with scrollable view properties', () => {

src/cdk/overlay/position/flexible-connected-position-strategy.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -741,8 +741,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
741741
let width: number, left: number, right: number;
742742

743743
if (isBoundedByLeftViewportEdge) {
744-
right = viewport.right - origin.x + this._viewportMargin;
745-
width = origin.x - viewport.left;
744+
right = viewport.width - origin.x + this._viewportMargin;
745+
width = origin.x - this._viewportMargin;
746746
} else if (isBoundedByRightViewportEdge) {
747747
left = origin.x;
748748
width = viewport.right - origin.x;

0 commit comments

Comments
 (0)