diff --git a/packages/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx b/packages/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx index 2e84567507633..52dab3cd7fc8f 100644 --- a/packages/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx +++ b/packages/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx @@ -15,6 +15,14 @@ const StyledMenuList = styled(NotRendered)(() => minWidth: 248, })); +function handleMenuScrollCapture(event: React.WheelEvent | React.TouchEvent) { + if (!event.currentTarget.contains(event.target as Node)) { + return; + } + + event.stopPropagation(); +} + const GridColumnMenuContainer = forwardRef( function GridColumnMenuContainer(props, ref) { const { hideMenu, colDef, id, labelledby, className, children, open, ...other } = props; @@ -39,6 +47,8 @@ const GridColumnMenuContainer = forwardRef - Column headers', () => { expect(screen.queryByRole('menu')).to.equal(null); }); }); + + it('should prevent wheel scroll event from closing the menu when scrolling within the menu', async () => { + const { user } = render( +
+ +
, + ); + + await user.click(within(getColumnHeaderCell(0)).getByLabelText('brand column menu')); + const menu = screen.getByRole('menu'); + + fireEvent.wheel(menu); + + await waitFor(() => { + expect(screen.queryByRole('menu')).not.to.equal(null); + }); + }); + + it('should close the column menu when the grid is scrolled', async () => { + const { user } = render( +
+ ({ id, name: id }))} + columns={[{ field: 'brand' }]} + /> +
, + ); + + await user.click(within(getColumnHeaderCell(0)).getByLabelText('brand column menu')); + + const scroller = document.querySelector('.MuiDataGrid-virtualScroller')!; + fireEvent.wheel(scroller, { deltaY: 120 }); + + await waitFor(() => { + expect(screen.queryByRole('menu')).to.equal(null); + }); + }); }); it("should use 'headerName' as the aria-label for the menu icon button", async () => {