Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiDataGrid] Change header actions trigger element and enable interactive children #7898

Merged
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8e8cf60
feat: POC for header cell interactions update
mgadewoll Jul 22, 2024
86bc3a1
test: update focus-utils test
mgadewoll Jul 22, 2024
bc787ed
test: update snapshots
mgadewoll Jul 22, 2024
7774ce5
refactor: implement alingment changes
mgadewoll Jul 25, 2024
e0a0efa
test: update tests and snapshots
mgadewoll Jul 25, 2024
5c6f7e0
test: fix tests
mgadewoll Jul 26, 2024
aa8c7bd
test: fix ref cypress test
mgadewoll Jul 26, 2024
9ab794f
test: update datagrid a11y test
mgadewoll Jul 26, 2024
a6dc1d3
refactor: update header cell styles to prevent visual changes
mgadewoll Jul 30, 2024
0d3a95c
chore: cleanup
mgadewoll Jul 30, 2024
6530609
test(VRT): update reference images
mgadewoll Jul 30, 2024
0683318
chore: add changelog
mgadewoll Jul 30, 2024
2649ebb
fix: ensure cell navigation in active cell does not change the active…
mgadewoll Jul 30, 2024
b2cd410
test: update cypress test
mgadewoll Jul 30, 2024
f58bd76
refactor: separate navigation for interactive and non-interactive hea…
mgadewoll Aug 2, 2024
1cf16a4
fix: hide global focus outline
mgadewoll Aug 2, 2024
512dedd
test: update snapshots
mgadewoll Aug 2, 2024
ecd5762
refactor: introduce onInteractiveChildrenFound
mgadewoll Aug 8, 2024
bbc3701
refactor: update focus_utils
mgadewoll Aug 8, 2024
f962aa9
refactor: use shared isDomeNode type guard
mgadewoll Aug 8, 2024
4773671
chore: cleanup
mgadewoll Aug 8, 2024
40d28a7
test: update snapshots
mgadewoll Aug 8, 2024
a6df757
refactor: remove obsolete onClickOutside override
mgadewoll Aug 8, 2024
36ad24e
refactor: remove need for shouldDisableInteractives
mgadewoll Aug 9, 2024
e23f347
chore: cleanup testing changes
mgadewoll Aug 9, 2024
ddfc793
test: update cypress test
mgadewoll Aug 9, 2024
d46087f
test: update datagrid cypress test
mgadewoll Aug 9, 2024
4a50293
[PR feedback] Simplify/remove `onInteractiveChildrenFound` behavior
cee-chen Aug 14, 2024
d338c34
Simplify logic further
cee-chen Aug 14, 2024
837b58a
Update Cypress tests to account for previous commit
cee-chen Aug 14, 2024
b3b1d1a
Update `HandleInteractiveChildren` to support a render prop that pass…
cee-chen Aug 17, 2024
f33f981
Attempt to simplify/clean up screen reader announcements
cee-chen Aug 17, 2024
23fb960
refactor: improve screen reader experience
mgadewoll Aug 27, 2024
ce11b57
test: update snapshots
mgadewoll Aug 27, 2024
2adfe3e
use aria-describedby to ensure improved screen readere xperience
mgadewoll Sep 2, 2024
793822b
test: update snapshots
mgadewoll Sep 2, 2024
c04b1a7
test(VRT): update reference images
mgadewoll Sep 2, 2024
98fed3a
minor code organization
cee-chen Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: update tests and snapshots
mgadewoll committed Aug 8, 2024
commit e0a0efa5109757730f1d68a8ce3c1a6c1d9cc594
Original file line number Diff line number Diff line change
@@ -31,51 +31,54 @@ exports[`EuiDataGridBodyCustomRender treats \`renderCustomGridBody\` as a render
data-focus-lock-disabled="disabled"
>
<div
class="euiDataGridHeaderCell__innerWrapper"
role="group"
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnA"
>
<div
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnA"
>
columnA
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
columnA
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
>
<button
aria-hidden="true"
aria-labelledby="euiDataGridCellHeader_generated-id_content euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button css-wvewty"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnA"
tabindex="-1"
>
<button
aria-labelledby="euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnA"
tabindex="-1"
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_content"
>
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
columnA
,
</p>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
<p
aria-live="assertive"
class="emotion-euiScreenReaderOnly"
@@ -111,51 +114,54 @@ exports[`EuiDataGridBodyCustomRender treats \`renderCustomGridBody\` as a render
data-focus-lock-disabled="disabled"
>
<div
class="euiDataGridHeaderCell__innerWrapper"
role="group"
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnB"
>
<div
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnB"
>
columnB
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
columnB
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
>
<button
aria-hidden="true"
aria-labelledby="euiDataGridCellHeader_generated-id_content euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button css-wvewty"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnB"
tabindex="-1"
>
<button
aria-labelledby="euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnB"
tabindex="-1"
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_content"
>
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
columnB
,
</p>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
<p
aria-live="assertive"
class="emotion-euiScreenReaderOnly"
Original file line number Diff line number Diff line change
@@ -35,51 +35,54 @@ exports[`EuiDataGridBodyVirtualized renders 1`] = `
data-focus-lock-disabled="disabled"
>
<div
class="euiDataGridHeaderCell__innerWrapper"
role="group"
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnA"
>
<div
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnA"
>
columnA
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
columnA
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
>
<button
aria-hidden="true"
aria-labelledby="euiDataGridCellHeader_generated-id_content euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button css-wvewty"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnA"
tabindex="-1"
>
<button
aria-labelledby="euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnA"
tabindex="-1"
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_content"
>
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
columnA
,
</p>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
<p
aria-live="assertive"
class="emotion-euiScreenReaderOnly"
@@ -115,51 +118,54 @@ exports[`EuiDataGridBodyVirtualized renders 1`] = `
data-focus-lock-disabled="disabled"
>
<div
class="euiDataGridHeaderCell__innerWrapper"
role="group"
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnB"
>
<div
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="columnB"
>
columnB
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
columnB
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
>
<button
aria-hidden="true"
aria-labelledby="euiDataGridCellHeader_generated-id_content euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button css-wvewty"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnB"
tabindex="-1"
>
<button
aria-labelledby="euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-columnB"
tabindex="-1"
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_content"
>
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
columnB
,
</p>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
<p
aria-live="assertive"
class="emotion-euiScreenReaderOnly"
Original file line number Diff line number Diff line change
@@ -33,31 +33,13 @@ describe('Cell focus utils', () => {
);

describe('does not render a focus trap', () => {
const props = {
...baseProps,
columns: [{ id: 'column', isExpandable: true, actions: {} }],
};

it('when header cells have actions', () => {
cy.mount(<EuiDataGrid {...props} />);

const headerCell = '[data-test-subj="dataGridHeaderCell-column"]';
const headerCellPopover =
'[data-test-subj="dataGridHeaderCellActionGroup-column"]';

// Should toggle the actions popover instead
cy.get(headerCell).click();
cy.get(headerCellPopover).should('be.visible');

// Keyboard behavior
cy.realPress('Escape');
cy.get(headerCellPopover).should('not.exist');
cy.realPress('Enter');
cy.get(headerCellPopover).should('exist');
});

it('when body cells are expandable', () => {
cy.mount(<EuiDataGrid {...props} />);
cy.mount(
<EuiDataGrid
{...baseProps}
columns={[{ id: 'column', isExpandable: true, actions: {} }]}
/>
);

const cell = '[data-test-subj="dataGridRowCell"]';
const cellAction = '[data-test-subj="euiDataGridCellExpandButton"]';
@@ -78,6 +60,44 @@ describe('Cell focus utils', () => {
});

describe('renders a focus trap', () => {
it('when header cells have actions', () => {
cy.mount(
<EuiDataGrid {...baseProps} columns={[{ id: 'column', actions: {} }]} />
);

const headerCell = '[data-test-subj="dataGridHeaderCell-column"]';
const headerCellActionsButton =
'[data-test-subj="dataGridHeaderCellActionButton-column"]';
const headerCellPopover =
'[data-test-subj="dataGridHeaderCellActionGroup-column"]';

// click behavior
// Should toggle the actions popover on actions button
cy.get(headerCell).click();
cy.get(headerCellPopover).should('not.exist');
cy.get(headerCellActionsButton).realClick();
cy.get(headerCellPopover).should('exist');
cy.get(headerCell).click();

// Keyboard behavior
// Enter focus trap
cy.realPress('Enter');

// toggle actions popover
cy.realPress('Enter');
cy.get(headerCellPopover).should('exist');
cy.realPress('Escape');
cy.get(headerCellPopover).should('not.exist');

// Exit the trap
cy.realPress('Escape');
cy.focused().should(
'have.attr',
'data-test-subj',
'dataGridHeaderCell-column'
);
});

it('when header cells do not have actions', () => {
cy.mount(
<EuiDataGrid
@@ -166,7 +186,6 @@ describe('Cell focus utils', () => {

cy.repeatRealPress('Tab', 4);
cy.focused()
.parent()
.should('have.attr', 'data-gridcell-row-index', '-1')
.should('have.attr', 'data-gridcell-column-index', '0');

@@ -197,8 +216,7 @@ describe('Cell focus utils', () => {
'data-test-subj',
'dataGridHeaderCellActionButton-column'
);
cy.focused()
.parent()
cy.get('[data-test-subj="dataGridHeaderCell-column"]')
.should('have.attr', 'data-gridcell-row-index', '-1')
.should('have.attr', 'data-gridcell-column-index', '0');
};
@@ -214,6 +232,7 @@ describe('Cell focus utils', () => {
};

cy.repeatRealPress('Tab', 4);
cy.realPress('Enter');
assertFocusedHeaderActions();
assertCanToggleActionsPopover();

Original file line number Diff line number Diff line change
@@ -189,14 +189,16 @@ describe('FocusTrappedChildren', () => {
const { container } = render(<FocusTrappedChildren cellEl={cell} />);

fireEvent.keyUp(cell, { key: 'Enter' });
waitFor(() => fireEvent.keyUp(cell, { key: 'Escape' }));
fireEvent.keyUp(cell, { key: 'Escape' });

expect(
container.querySelector('[data-focus-lock-disabled]')
).toHaveAttribute('data-focus-lock-disabled', 'disabled');
await waitFor(() => {
expect(
container.querySelector('[data-focus-lock-disabled]')
).toHaveAttribute('data-focus-lock-disabled', 'disabled');

expect(cell.querySelector('button')).toHaveAttribute('tabindex', '-1');
expect(cell).toHaveFocus();
expect(cell.querySelector('button')).toHaveAttribute('tabindex', '-1');
expect(cell).toHaveFocus();
});
});

it('does nothing if the cell is not entered', () => {
Original file line number Diff line number Diff line change
@@ -23,51 +23,54 @@ exports[`EuiDataGridHeaderCell renders 1`] = `
data-focus-lock-disabled="disabled"
>
<div
class="euiDataGridHeaderCell__innerWrapper"
role="group"
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="someColumn"
>
<div
class="euiDataGridColumnResizer"
data-test-subj="dataGridColumnResizer"
style="margin-right: 0px;"
/>
<div
class="euiDataGridHeaderCell__content"
title="someColumn"
>
someColumn
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
someColumn
</div>
<div
class="euiPopover emotion-euiPopover-block-EuiDataGridHeaderCell"
>
<button
aria-hidden="true"
aria-labelledby="euiDataGridCellHeader_generated-id_content euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button css-wvewty"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-someColumn"
tabindex="-1"
>
<button
aria-labelledby="euiDataGridCellHeader_generated-id_actions"
class="euiDataGridHeaderCell__button"
data-euigrid-tab-managed="true"
data-test-subj="dataGridHeaderCellActionButton-someColumn"
tabindex="-1"
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_content"
>
<div
class="euiDataGridHeaderCell__icon"
>
<span
color="text"
data-euiicon-type="boxesVertical"
/>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
someColumn
,
</p>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_actions"
>
Click to view column header actions
</p>
</button>
</div>
<p
hidden=""
id="euiDataGridCellHeader_generated-id_sorting"
/>
<p
aria-live="assertive"
class="emotion-euiScreenReaderOnly"