From 5eed68ea1a3342418d46f9a49e8e6568e38dd42e Mon Sep 17 00:00:00 2001 From: Matheus Wichman Date: Thu, 28 Oct 2021 08:36:14 -0300 Subject: [PATCH] [DataGrid] Prevent scroll when selecting rows (#2558) (#2999) --- .../grid/components/cell/GridCell.tsx | 24 ++++++++-- test/e2e/fixtures/DataGrid/RowSelection.tsx | 45 +++++++++++++++++++ test/e2e/index.test.ts | 16 +++++++ 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 test/e2e/fixtures/DataGrid/RowSelection.tsx diff --git a/packages/grid/_modules_/grid/components/cell/GridCell.tsx b/packages/grid/_modules_/grid/components/cell/GridCell.tsx index b4e55dd7e04f..8abc7e675b6c 100644 --- a/packages/grid/_modules_/grid/components/cell/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/cell/GridCell.tsx @@ -32,6 +32,20 @@ export interface GridCellProps { tabIndex: 0 | -1; } +// Based on https://stackoverflow.com/a/59518678 +let cachedSupportsPreventScroll: boolean; +function doesSupportPreventScroll(): boolean { + if (cachedSupportsPreventScroll === undefined) { + document.createElement('div').focus({ + get preventScroll() { + cachedSupportsPreventScroll = true; + return false; + }, + }); + } + return cachedSupportsPreventScroll; +} + export const GridCell = React.memo(function GridCell(props: GridCellProps) { const { align, @@ -146,10 +160,14 @@ export const GridCell = React.memo(function GridCell(props: GridCellProps) { if (cellRef.current && !cellRef.current.contains(doc.activeElement!)) { const focusableElement = cellRef.current!.querySelector('[tabindex="0"]') as HTMLElement; - if (focusableElement) { - focusableElement!.focus(); + const elementToFocus = focusableElement || cellRef.current; + + if (doesSupportPreventScroll()) { + elementToFocus.focus({ preventScroll: true }); } else { - cellRef.current!.focus(); + const scrollPosition = apiRef.current.getScrollPosition(); + elementToFocus.focus(); + apiRef.current.scroll(scrollPosition); } } }); diff --git a/test/e2e/fixtures/DataGrid/RowSelection.tsx b/test/e2e/fixtures/DataGrid/RowSelection.tsx new file mode 100644 index 000000000000..6d68734f79e5 --- /dev/null +++ b/test/e2e/fixtures/DataGrid/RowSelection.tsx @@ -0,0 +1,45 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; + +const baselineProps = { + rows: [ + { + id: 0, + brand: 'Nike', + year: 1990, + }, + { + id: 1, + brand: 'Adidas', + year: 1995, + }, + { + id: 2, + brand: 'Puma', + year: 1993, + }, + { + id: 3, + brand: 'Gucci', + year: 1996, + }, + ], + columns: [ + { field: 'brand', width: 120 }, + { field: 'year', width: 120 }, + ], +}; + +export default function RowSelection() { + return ( +
+ +
+ ); +} diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 45176ee67300..347b298e4160 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -194,5 +194,21 @@ describe('e2e', () => { ), ).to.contain('Mui-selected'); }); + + it('should not scroll when changing the selected row', async () => { + await renderFixture('DataGrid/RowSelection'); + await page.click('[role="cell"][data-rowindex="0"]'); + await page.evaluate(() => + document.querySelector('[role="cell"][data-rowindex="3"]')!.scrollIntoView(), + ); + const scrollTop = await page.evaluate( + () => document.querySelector('.MuiDataGrid-window')!.scrollTop!, + ); + expect(scrollTop).not.to.equal(0); + await page.click('[role="cell"][data-rowindex="3"]'); + expect( + await page.evaluate(() => document.querySelector('.MuiDataGrid-window')!.scrollTop!), + ).to.equal(scrollTop); + }); }); });