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] Simplify & DRY out cell/header focus #7448

Merged
merged 20 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d17b6a5
[organization] Move cell-related files to their own folder
cee-chen Nov 23, 2023
d670e85
Add new focus util
cee-chen Nov 23, 2023
a79faa3
[EuiDataGridCell] Replace focus logic with new focus util
cee-chen Jan 3, 2024
3c04c75
[EuiDataGridCell] Continue removing now-unnecessary focus timeouts & …
cee-chen Jan 3, 2024
21ae96c
[downstream tests] Update tests to account for cellActions change
cee-chen Jan 4, 2024
1845f5a
[EuiDataGridCell] Remove Jest focus tests in favor of Cypress ones
cee-chen Jan 3, 2024
fdb932a
[EuiDataGridHeaderCell] Replace focus logic with new util
cee-chen Jan 4, 2024
4c2a5d3
[EuiDataGridHeaderCell] Screen reader focus improvements + E2E tests
cee-chen Jan 4, 2024
165e6e2
[Docs] Update intended final focus behavior
cee-chen Jan 4, 2024
f39ba58
[Focus] Make header always interactive & navigable
cee-chen Jan 4, 2024
31adcba
🔥 Remove `headerIsInteractive` logic entirely
cee-chen Jan 4, 2024
5c9214e
[misc perf] Remove dependency on useCallback fn
cee-chen Jan 4, 2024
d844561
[downstream tests] Update data grid tests w/ keyboard interactions
cee-chen Jan 4, 2024
72df313
misc test cleanup
cee-chen Jan 4, 2024
45b3f31
[downstream tests] snapshot updates
cee-chen Jan 4, 2024
292b7d8
changelog
cee-chen Jan 4, 2024
0bcef9b
Typescript lint workaround
cee-chen Jan 4, 2024
41ed92e
Add screen reader text for Enter key behavior
cee-chen Jan 4, 2024
d6c70f6
[PR feedback] Fix focus fighting bug + add E2E regression test for be…
cee-chen Jan 5, 2024
1d9e46f
Fix flaky Cypress test
cee-chen Jan 5, 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
7 changes: 7 additions & 0 deletions changelogs/upcoming/7448.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
**Accessibility**

- `EuiDataGrid`'s keyboard/screenreader experience has been tweaked to be more consistent for varying complex data:
- Headers are now always navigable by arrow key, regardless of whether the header cells contain interactive content
- Non-expandable cells containing any amount of interactive content now must be entered via Enter or F2 keypress
- Expandable cells continue to be toggled via Enter or F2 keypress
- `EuiDataGrid` now provides a direct screen reader hint for Enter key behavior for expandable & interactive cells
109 changes: 29 additions & 80 deletions src-docs/src/views/datagrid/cells_popovers/datagrid_cells_example.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React, { Fragment } from 'react';
import React from 'react';
import { Link } from 'react-router-dom';

import { GuideSectionTypes } from '../../../components';
import {
EuiDataGrid,
EuiCode,
EuiCallOut,
EuiBasicTable,
EuiSpacer,
EuiText,
EuiListGroupItem,
} from '../../../../../src';
Expand Down Expand Up @@ -64,7 +62,7 @@ export const DataGridCellsExample = {
],
title: 'Cell actions',
text: (
<Fragment>
<>
<p>
In addition to making a cell expandable, you can add more custom
actions by setting <EuiCode>columns.cellActions</EuiCode>. These
Expand Down Expand Up @@ -97,7 +95,7 @@ export const DataGridCellsExample = {
<EuiCode>cellAction</EuiCode> each, while the country column
provides 2 <EuiCode>cellAction</EuiCode>s.
</p>
</Fragment>
</>
),
props: {
EuiDataGrid,
Expand Down Expand Up @@ -157,7 +155,7 @@ export const DataGridCellsExample = {
},
],
text: (
<Fragment>
<>
<p>
<strong>EuiDataGrid</strong> tracks and manages complicated focus
state management based upon the content of the individual inner
Expand All @@ -166,93 +164,44 @@ export const DataGridCellsExample = {
<h3>Initial focus</h3>
<ul>
<li>
When tabbing to the grid before it has received focus, the first
cell of either the header (if it is interaction) or first content
When tabbing to the grid before it has received focus, the header
cell is focused.
</li>
<li>Datagrid does not auto-focus on mount / page load</li>
<li>
When removing focus from the grid and then returning, the last
focused cell remains focused.
When tabbing away from the grid and then returning, the last
focused cell will regain focus.
</li>
<li>
If the last focused cell has been scrolled out of view, the first
header cell receives focus instead.
</li>
</ul>
<h3>Click and key events</h3>
<ul>
<li>
Clicking on an interactive cell (not its content) should focus on
the cell, or if it has only one interactive element the focus
should shift to the element.
Clicking on an interactive cell or its content should focus on the
cell.
</li>
<li>
The up, down, left, and right arrow keys can be pressed to
navigate between cells.
</li>
<li>
For expandable cells, either the Enter or F2 keys can be pressed
interchangeably to toggle the cell popover. The Escape key will
close the popover.
</li>
<li>
Clicking on an interactive element within a cell the focus should
always remain on that element, not shift to the cell or another
element unless a subsequent user action changes it.
For non-expandable cells with interactive content, either the
Enter or F2 keys can be pressed to enter a focus trap, allowing
users to Tab between the cell's content. The Escape key will exit
the cell trap.
</li>
<li>
Enter or F2 can be used interchangeably to enter inner cell focus
if the logic below allows it.
For non-expandable cells with no interactive content, the cell
alone will receive focus, with no inner content action.
</li>
</ul>
<h3>
The content and expandability of the cells dictate the focus target
of the cell
</h3>
<p>
The following combinations of focus are maintained to provide for a
good balance between accessibility and ease of use while navigating
the grid with your keyboard.
</p>
<EuiBasicTable
columns={[
{
field: 'expandable',
name: 'Expandablity',
},
{
field: 'contents',
name: 'Cell contains',
},
{
field: 'result',
name: 'Resulting focus',
width: '50%',
mobileOptions: {
width: '100%',
},
},
]}
items={[
{
id: '1',
expandable: 'Not expandable',
contents: 'No interactive elements',
result:
'Cell alone receives the focus, with no possible inner focus action',
},
{
id: '2',
expandable: 'Not expandable',
contents: 'Single interactive element',
result:
'The single inner element within the cell receives focus',
},
{
id: '3',
expandable: 'Not expandable',
contents: 'Multiple interactive elements',
result:
'The cell will allow a non-expanding focus trap on Enter keyDown',
},
{
id: '4',
expandable: 'Is expandable',
contents:
'Any combination of interactive / non-interactive elements',
result: 'The cell will focus on the expansion action',
},
]}
/>
<EuiSpacer />
<EuiCallOut
color="warning"
title="Don't turn off cell expansion when the width of the column is unknown"
Expand All @@ -265,7 +214,7 @@ export const DataGridCellsExample = {
when you cannot control the width can lead to hidden focus because
the content is truncated.
</EuiCallOut>
</Fragment>
</>
),
demo: <DataGridFocus />,
},
Expand Down
49 changes: 26 additions & 23 deletions src-docs/src/views/datagrid/cells_popovers/focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,7 @@ export default () => {
const columns = [
{
id: 'no-interactives not expandable',
display: (
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
<EuiFlexItem grow={false}>
<EuiButtonIcon
aria-label="column settings"
iconType="gear"
onClick={() => {}}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBadge>0 interactive</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
),
display: <EuiBadge>0 interactive</EuiBadge>,
isExpandable: false,
actions: false,
},
Expand All @@ -95,21 +82,23 @@ export default () => {
},
{
id: 'one-interactive not expandable',
display: <EuiBadge>1 interactive</EuiBadge>,
display: (
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
<EuiButtonIcon
aria-label="column settings"
iconType="gear"
onClick={() => {}}
/>
<EuiBadge>1 interactive</EuiBadge>
</EuiFlexGroup>
),
isExpandable: false,
actions: false,
},
{
id: 'one-interactives is expandable',
display: (
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
<EuiFlexItem grow={false}>
<EuiButtonIcon
aria-label="column settings"
iconType="gear"
onClick={() => {}}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToken
iconType="expandMini"
Expand All @@ -128,7 +117,21 @@ export default () => {
},
{
id: 'two-interactives not expandable',
display: <EuiBadge>2 interactive</EuiBadge>,
display: (
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
<EuiButtonIcon
aria-label="column settings"
iconType="gear"
onClick={() => {}}
/>
<EuiButtonIcon
aria-label="column settings"
iconType="gear"
onClick={() => {}}
/>
<EuiBadge>2 interactive</EuiBadge>
</EuiFlexGroup>
),
isExpandable: false,
actions: false,
},
Expand Down
Loading
Loading