diff --git a/src/components-lib/media-grid-controller.ts b/src/components-lib/media-grid-controller.ts index 1c8b06cf..156433fb 100644 --- a/src/components-lib/media-grid-controller.ts +++ b/src/components-lib/media-grid-controller.ts @@ -286,8 +286,12 @@ export class MediaGridController { // Reset the column CSS sizes first. this._setColumnSizeStyles(); - // Need to recreate the masonry layout since the column width will differ. - this._createMasonry(); + // Update the column width on the existing Masonry instance rather than + // destroying and recreating it. A destroy resets the container height to + // 0, which can cause an ancestor scrollbar to appear/disappear, changing + // the available width and triggering an infinite resize oscillation. + this._masonry?.option?.({ columnWidth: this._getColumnSize() }); + this._throttledLayout(); } } diff --git a/tests/components-lib/media-grid-controller.test.ts b/tests/components-lib/media-grid-controller.test.ts index 4e4c8edd..d7fb562b 100644 --- a/tests/components-lib/media-grid-controller.test.ts +++ b/tests/components-lib/media-grid-controller.test.ts @@ -491,7 +491,7 @@ describe('MediaGridController', () => { expect(masonry.layout).toBeCalled(); }); - it('should re-create masonry when host size changes', () => { + it('should update masonry column width when host size changes', () => { const children = createChildren(); const parent = createParent({ children: children }); createController(parent); @@ -508,18 +508,16 @@ describe('MediaGridController', () => { // Clear mock state. vi.mocked(Masonry).mockClear(); vi.mocked(masonry.layout)?.mockClear(); + vi.mocked(masonry.option)?.mockClear(); // Resize the host. setElementWidth(parent, 3000); triggerResizeObserver('host'); - // Masonry should be reconstructed, styles set and layout called. - expect(Masonry).toBeCalledWith( - parent, - expect.objectContaining({ - columnWidth: 599, - }), - ); + // Masonry should not be recreated, but column width should be updated + // via option() and layout should be called. + expect(Masonry).not.toBeCalled(); + expect(masonry.option).toBeCalledWith({ columnWidth: 599 }); expect( parent.style.getPropertyValue('--advanced-camera-card-grid-column-size'), ).toBe('599px'); @@ -528,10 +526,12 @@ describe('MediaGridController', () => { // Clear mock state. vi.mocked(Masonry).mockClear(); vi.mocked(masonry.layout)?.mockClear(); + vi.mocked(masonry.option)?.mockClear(); - // Triger with the same sizes. + // Trigger with the same sizes. triggerResizeObserver('host'); expect(Masonry).not.toBeCalled(); + expect(masonry.option).not.toBeCalled(); expect(masonry.layout).not.toBeCalled(); });