Skip to content

Commit

Permalink
[EuiDataGrid] Fix column actions not working for draggable datagrid i…
Browse files Browse the repository at this point in the history
…nside modals (#8135)
  • Loading branch information
mgadewoll authored Nov 14, 2024
1 parent a7c86a5 commit 316a864
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 33 deletions.
4 changes: 4 additions & 0 deletions packages/eui/changelogs/upcoming/8135.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**Bug fixes**

- Fixed an `EuiDataGrid` bug where column actions where not clickable when `EuiDataGrid` with `columnVisibility.canDragAndDropColumns` was used inside a modal

Original file line number Diff line number Diff line change
@@ -1,41 +1,20 @@
import React, { useState } from 'react';
import React, { useState, useCallback } from 'react';
import { faker } from '@faker-js/faker';

import {
EuiDataGrid,
EuiAvatar,
EuiToolTip,
EuiButtonIcon,
} from '../../../../../src/components';

const CustomHeaderCell = ({ title }) => (
<>
<span>{title}</span>
<EuiToolTip content="tooltip content">
<EuiButtonIcon
iconType="questionInCircle"
aria-label="Additional information"
color="primary"
/>
</EuiToolTip>
</>
);
import { EuiDataGrid, EuiAvatar } from '../../../../../src/components';

const columns = [
{
id: 'avatar',
initialWidth: 40,
isResizable: false,
actions: false,
},
{
id: 'name',
displayAsText: 'Name',
display: <CustomHeaderCell title="Name" />,
initialWidth: 100,
},
{
id: 'email',
display: <CustomHeaderCell title="Email" />,
},
{
id: 'city',
Expand Down Expand Up @@ -67,21 +46,42 @@ for (let i = 1; i < 5; i++) {
}

export default () => {
const [pagination, setPagination] = useState({ pageIndex: 0 });

const [visibleColumns, setVisibleColumns] = useState(
columns.map(({ id }) => id)
);

const setPageIndex = useCallback(
(pageIndex) =>
setPagination((pagination) => ({ ...pagination, pageIndex })),
[]
);
const setPageSize = useCallback(
(pageSize) =>
setPagination((pagination) => ({
...pagination,
pageSize,
pageIndex: 0,
})),
[]
);

return (
<EuiDataGrid
aria-label="DataGrid demonstrating column reordering on drag"
aria-label="DataGrid demonstrating column sizing constraints"
columns={columns}
columnVisibility={{
visibleColumns: visibleColumns,
setVisibleColumns: setVisibleColumns,
canDragAndDropColumns: true,
}}
rowCount={data.length}
renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]}
pagination={{
...pagination,
onChangeItemsPerPage: setPageSize,
onChangePage: setPageIndex,
}}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import React, { useState } from 'react';
import { EuiDataGrid, EuiDataGridProps } from '../../index';
import { EuiModal, EuiModalBody } from '../../../modal';

describe('draggable columns', () => {
const columns = [
Expand Down Expand Up @@ -284,4 +285,40 @@ describe('draggable columns', () => {
cy.get('[data-popover-open]').should('not.exist');
});
});

describe('inside a modal', () => {
it('should execute column actions on click', () => {
cy.realMount(
<EuiModal onClose={() => {}}>
<EuiModalBody>
<StatefulDataGrid />
</EuiModalBody>
</EuiModal>
);

cy.get('[data-test-subj=dataGridHeaderCell-a]').realHover();
cy.wait(50); // wait until actions button transition is progressed enough for the button to be clickable
cy.get('[data-test-subj=dataGridHeaderCellActionButton-a]').realClick();
cy.get('[data-popover-open]').should('have.focus');

cy.get(
'.euiListGroupItem:last-child .euiListGroupItem__button'
).realClick();

cy.get('[data-test-subj=dataGridHeaderCell-a]').should(
'have.attr',
'data-gridcell-column-index',
'1'
);
cy.get('[data-test-subj=dataGridHeaderCell-b]').should(
'have.attr',
'data-gridcell-column-index',
'0'
);

cy.get('[data-test-subj=euiDataGridHeaderColumnActions]').should(
'not.exist'
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,23 @@ export const DraggableColumn: FunctionComponent<{
const { setFocusedCell } = useContext(DataGridFocusContext);
const handleOnMouseDown: MouseEventHandler = useCallback(
(e) => {
const openFocusTrap = document.querySelector(
const openFocusTraps = document.querySelectorAll(
'[data-focus-lock-disabled="false"]'
);
if (
!!openFocusTrap && // If a focus trap is open somewhere on the page
!openFocusTrap.contains(e.target as Node) && // & the focus trap doesn't belong to this header
e.target !== actionsPopoverToggle // & we're not closing the actions popover toggle
) {
const validOpenFocusTraps = [...openFocusTraps].filter(
(focusTrap) => !focusTrap.contains(e.currentTarget as Node) // remove containing focus traps (e.g. modals or flyouts)
);

const shouldDispatchEvent = validOpenFocusTraps.some(
(focusTrap) =>
!!focusTrap && // If there is a focus trap open
!focusTrap.contains(e.target as Node) && // & if it doesn't contain the target
e.target !== actionsPopoverToggle // & we're not closing the actions popover toggle
);

if (shouldDispatchEvent) {
// Trick the focus trap lib into registering an outside click -
// the drag/drop lib otherwise otherwise prevents the event 💀
// the drag/drop lib otherwise prevents the event 💀
document.dispatchEvent(new MouseEvent('mousedown'));
}
setTimeout(() => {
Expand Down

0 comments on commit 316a864

Please sign in to comment.