Skip to content

Commit

Permalink
[XGrid] Close column header menu when resizing column (#1989)
Browse files Browse the repository at this point in the history
* [XGrid] Close column header menu when resizing column

* Run prettier

* Fix test

* Remove dummy line

* Run Prettier

* Fix browser tests

* Run prettier

* Fix

* Fix comments

* Remove it.only

* Remove useless expect

* Remove 'raf'

* Clean listeners when unmounting the grid in useGridColumnResize

* Remove commented test lines

* Code review

* Add test to check behavior when resizing another column

* Remove 'only'

* Move test in describe

* Remove async

* Code review

* Code review
  • Loading branch information
flaviendelangle authored Jul 7, 2021
1 parent 7964e78 commit 55972c6
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import clsx from 'clsx';
import { useGridSelector } from '../../hooks/features/core/useGridSelector';
import { optionsSelector } from '../../hooks/utils/optionsSelector';
import { useGridApiContext } from '../../hooks/root/useGridApiContext';
import { GRID_COLUMN_HEADER_SEPARATOR_RESIZABLE_CSS_CLASS } from '../../constants';

export interface GridColumnHeaderSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {
resizable: boolean;
Expand All @@ -27,7 +28,7 @@ export const GridColumnHeaderSeparator = React.memo(function GridColumnHeaderSep
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
<div
className={clsx('MuiDataGrid-columnSeparator', {
'MuiDataGrid-columnSeparator--resizable': resizable,
[GRID_COLUMN_HEADER_SEPARATOR_RESIZABLE_CSS_CLASS]: resizable,
'Mui-resizing': resizing,
})}
style={{ minHeight: height, opacity: showColumnRightBorder ? 0 : 1 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export function GridColumnHeadersItemCollection(props: GridColumnHeadersItemColl
: -1;
const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === col.field;
const open = columnMenuState.open && columnMenuState.field === col.field;

return (
<GridColumnHeaderItem
key={col.field}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { GridApiRef } from '../../../models/api/gridApiRef';
import { useGridApiMethod } from '../../root/useGridApiMethod';
import { useLogger } from '../../utils/useLogger';
import { useGridState } from '../core/useGridState';
import { useGridApiEventHandler } from '../../root';
import { GRID_COLUMN_RESIZE_START } from '../../../constants';

export const useGridColumnMenu = (apiRef: GridApiRef): void => {
const logger = useLogger('useGridColumnMenu');
Expand Down Expand Up @@ -42,6 +44,22 @@ export const useGridColumnMenu = (apiRef: GridApiRef): void => {
[logger, showColumnMenu, hideColumnMenu, gridState],
);

const handleColumnResizeStart = React.useCallback(() => {
setGridState((oldState) => {
if (oldState.columnMenu.open) {
return {
...oldState,
columnMenu: {
...oldState.columnMenu,
open: false,
},
};
}

return oldState;
});
}, [setGridState]);

React.useEffect(() => {
if (gridState.isScrolling) {
hideColumnMenu();
Expand All @@ -57,4 +75,6 @@ export const useGridColumnMenu = (apiRef: GridApiRef): void => {
},
'ColumnMenuApi',
);

useGridApiEventHandler(apiRef, GRID_COLUMN_RESIZE_START, handleColumnResizeStart);
};
101 changes: 101 additions & 0 deletions packages/grid/x-grid/src/tests/columnHeaders.XGrid.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as React from 'react';
import {
createClientRenderStrictMode,
// @ts-expect-error need to migrate helpers to TypeScript
fireEvent,
// @ts-expect-error need to migrate helpers to TypeScript
screen,
// @ts-expect-error need to migrate helpers to TypeScript
waitFor,
} from 'test/utils';
import { expect } from 'chai';
import { GRID_COLUMN_HEADER_SEPARATOR_RESIZABLE_CSS_CLASS, XGrid } from '@material-ui/x-grid';
import { getColumnHeaderCell } from 'test/utils/helperFn';

const isJSDOM = /jsdom/.test(window.navigator.userAgent);

describe('<XGrid /> - Column Headers', () => {
// TODO v5: replace with createClientRender
const render = createClientRenderStrictMode();

const baselineProps = {
autoHeight: isJSDOM,
disableColumnResize: false,
rows: [
{
id: 0,
brand: 'Nike',
foundationYear: 1964,
},
{
id: 1,
brand: 'Adidas',
foundationYear: 1949,
},
{
id: 2,
brand: 'Puma',
foundationYear: 1948,
},
],
};

describe('GridColumnHeaderMenu', () => {
it('should close the menu of a column when resizing this column', async () => {
render(
<div style={{ width: 300, height: 500 }}>
<XGrid
{...baselineProps}
columns={[
{ field: 'brand', resizable: true },
{ field: 'foundationYear', resizable: true },
]}
/>
</div>,
);

const columnCell = getColumnHeaderCell(0);

const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]');

fireEvent.click(menuIconButton);
await waitFor(() => expect(screen.queryByRole('menu')).not.to.equal(null));

const separator = columnCell.querySelector('.MuiDataGrid-iconSeparator');
fireEvent.mouseDown(separator);
// TODO remove mouseUp once useGridColumnReorder will handle cleanup properly
fireEvent.mouseUp(separator);
await waitFor(() => expect(screen.queryByRole('menu')).to.equal(null));
});

it('should close the menu of a column when resizing another column', async () => {
render(
<div style={{ width: 300, height: 500 }}>
<XGrid
{...baselineProps}
columns={[
{ field: 'brand', resizable: true },
{ field: 'foundationYear', resizable: true },
]}
/>
</div>,
);

const columnWithMenuCell = getColumnHeaderCell(0);
const columnToResizeCell = getColumnHeaderCell(1);

const menuIconButton = columnWithMenuCell.querySelector('button[aria-label="Menu"]');

fireEvent.click(menuIconButton);
await waitFor(() => expect(screen.queryByRole('menu')).not.to.equal(null));

const separator = columnToResizeCell.querySelector(
`.${GRID_COLUMN_HEADER_SEPARATOR_RESIZABLE_CSS_CLASS}`,
);
fireEvent.mouseDown(separator);
// TODO remove mouseUp once useGridColumnReorder will handle cleanup properly
fireEvent.mouseUp(separator);
await waitFor(() => expect(screen.queryByRole('menu')).to.equal(null));
});
});
});

0 comments on commit 55972c6

Please sign in to comment.