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

Conversation

cee-chen
Copy link
Contributor

@cee-chen cee-chen commented Jan 4, 2024

Summary

closes #5690

Extra context: I originally spiked most of this out during the cell redesigns (#7382) probably because the repeated logic or keyboard UX slightly bothered me 😅 It turned out a larger set of changes than I wanted for a single release, so I split it out to a separate branch for later. Since it was very close to completion, I figured I'd finish it up to clean out my lingering 2023 work.

As always, please follow along by commit. While it looks like more lines of code were added in this PR, those were primarily all tests (a good thing to have more of) and snapshots diffs. From actual source code, a net ~500 or so lines were removed.

Main changes in this PR:

datagrid_focus

  1. I removed all logic around detecting headerIsInteractive. From now on, data grid headers can ALWAYS be navigated to via arrow keys, regardless of whether or not header cells have interactive content or not.

    • I believe this logic was originally added to make EuiDataGrid behave like the "simple" data grid example in https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/data-grids/#examples.
    • However, I don't think this is a pattern worth emulating. EuiDataGrids don't get used for simple data, otherwise devs would reach for EuiBasicTable instead. I strongly feel the extra code, state, and mutation observer was not worth the unnecessary UX, and frankly I also think the UX is confusing and creates inconsistencies between data grids.
  2. Non-expandable cells that only contain 1 interactive child element no longer auto-focus that element, but instead render a focus trap

    • Again, I believe this logic was trying to mimic the above WCAG demo behavior, but frankly, I don't consider that behavior worth emulating. To reiterate, our data grid usages in production are vastly more complex than these simplistic demos.
    • The logic also introduced accessibility issues (see above [EuiDataGrid] Focus behavior on cells that are isExpandable: false and have 1 interactive child  #5690, accessibility concerns) where other non-interactive content in the cell would not be accessible to keyboard users.
    • A focus trap is overall more consistent with how other cells behave (Enter key) and more accessible to a variety of cell content.
  3. Cell screen reader text now contains instructions for the Enter keypress behavior in addition to current column position.

For the majority of default EuiDataGrid use cases (expandable cells & column headers with actions), nothing should have changed or regressed from before.

QA

General checklist

  • Browser QA
    - [ ] Checked in both light and dark modes
    - [ ] Checked in mobile
    • Checked in Chrome, Safari, Edge, and Firefox
    • Checked for accessibility including keyboard-only and screenreader modes
  • Docs site QA
  • Code quality checklist
  • Release checklist
    • A changelog entry exists and is marked appropriately.
      - [ ] If applicable, added the breaking change issue label (and filled out the breaking change checklist)
  • Designer checklist
    - [ ] Updated the Figma library counterpart

- there's enough now that it's clogging up the `body/` folder and it makes sense to
- all of the removed methods are now totally unnecessary and handled as-is by `HandleInteractiveChildren`
- cell actions are rendered in the DOM, just not visible, which saves us from having to add a bunch of extra hover/focus state trackers
- all of the removed methods are now totally unnecessary and handled as-is by `HandleInteractiveChildren
- auto focus the column header actions button instead of the wrapping grid cell, as it contains more SR information than just the cell

- fix cell focus border to appear correctly as before

- write E2E Cypress tests to replace old Jest tests
+ better header focus trap testing
- removes the need for a bunch of extra state/props, a mutation observer, hooks, etc.

- it really doesn't add anything except extra cruft and inconsistency to have the header not be navigable to, hence this entire PR removing it
- to account for header now always being navigable no matter what
- remove unnecessary `getGridData()` call which isn't asserting on anything
- my local vscode doesn't complain about this, but CLI does - not totally sure why or if this makes sense :|
@cee-chen cee-chen force-pushed the datagrid/cell-focus branch from c767730 to e0a1584 Compare January 4, 2024 23:25
@cee-chen cee-chen force-pushed the datagrid/cell-focus branch from e0a1584 to 41ed92e Compare January 4, 2024 23:30
@cee-chen cee-chen marked this pull request as ready for review January 4, 2024 23:31
@cee-chen cee-chen requested a review from a team as a code owner January 4, 2024 23:31
@cee-chen cee-chen requested a review from 1Copenut January 4, 2024 23:31
@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 4, 2024

@1Copenut Hey hey! I was hoping you could review this since this is primarily accessibility driven in improvements (in addition to the side benefit of lots of DRYing out/removal of code) 🙏

@cee-chen cee-chen force-pushed the datagrid/cell-focus branch from 8a2868d to d6c70f6 Compare January 5, 2024 18:44
@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 5, 2024

@1Copenut Header focus fighting should be fixed once staging is done updating! Thank you so much for catching that bug!

- caused by race condition with ref not updating `HandleInteractiveChildren`
@cee-chen cee-chen force-pushed the datagrid/cell-focus branch from 9f8601e to 1d9e46f Compare January 5, 2024 21:26
@kibanamachine
Copy link

Preview staging links for this PR:

@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

Copy link
Contributor

@1Copenut 1Copenut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 LGTM! I tested the QA requirements you laid out in two rounds--one before we discovered the regression in header row behavior and once after to verify the fix. This gave me two opportunities to drive the new UX for handling rows with one interactive element.

This was the right call, to make cells with 1 or N interactive elements behave the same. I was able to internalize the pattern quickly and didn't feel the extra click to do things like open the Actions menu was an inconvenience.

Testing groups:

  • Evergreen browsers [Chrome, Firefox, Edge, Safari]
  • MacOS Safari + VoiceOiver
  • Win10 Firefox + NVDA
  • Win10 Chrome + NVDA
  • Win10 Chrome + JAWS

<EuiI18n
// eslint-disable-next-line local/i18n
token="euiDataGridCell.focusTrapEnterPrompt"
default="Press the Enter key to interact with this cell's contents."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one thing I've been mulling over in testing. I love the clear directions to enter the focus trap. I wonder if we need explanation to exit the focus trap via the ESC key. My hunch is no, at least until data tells us otherwise. I wonder if the Research team would be up for a screen reader testing session.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering that as well - thanks for raising it! I think I also lean towards waiting to see if it's needed before adding. I'd love for us to start doing screen reader research!

Comment on lines +24 to +32
* This internal utility component is used by all cells, both header and body/footer cells.
* It always handles:
* 1. Removing any interactive children from keyboard tab order on cell mount
* 2. Listening for focus on any interactive children and updating the cell focus context
*
* It should *only* render focus traps for:
* 1. Header cells that are `actions: false` but still have interactive children
* 2. Body cells that are `isExpandable: false` but still have interactive children
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This explanation of the utility was especially helpful in QA testing. Between this documentation and the clear separation of concerns, I was able to answer 90% of my own questions. This is greatly appreciated by me and will pay dividends for future consumers. Thanks Cee!

* focus trap that can be entered with the Enter key, which cycles keyboard tabs
* through the cell contents only, and exited with the Escape key
*/
export const FocusTrappedChildren: FunctionComponent<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This drives so much better with screen readers, having one interaction pattern for 1 or N number of interactive elements. It felt natural and I didn't notice the extra click.

@cee-chen
Copy link
Contributor Author

cee-chen commented Jan 8, 2024

Thanks a million for the QA and feedback Trevor!! Super happy this was a net screen reader improvement ✨

Going to merge this in after today's release to spread out changes a bit.

@cee-chen cee-chen merged commit e67ef5d into elastic:main Jan 8, 2024
7 checks passed
@cee-chen cee-chen deleted the datagrid/cell-focus branch January 8, 2024 19:16
cee-chen added a commit to elastic/kibana that referenced this pull request Jan 24, 2024
`v92.0.0-backport.0`⏩ `v92.1.1`

---

## [`v92.1.1`](https://github.com/elastic/eui/releases/v92.1.1)

**Bug fixes**

- Minor `EuiDataGrid` cell performance fixes
([#7465](elastic/eui#7465))

## [`v92.1.0`](https://github.com/elastic/eui/releases/v92.1.0)

- Updated `EuiResizableButton` to allow customizing the `indicator`
style with either `handle` (default) or `border`
([#7455](elastic/eui#7455))
- Enhanced `EuiResizableContainer` to preserve the drag/resize event
when the user's mouse leaves the parent container and re-enters
([#7456](elastic/eui#7456))

**Bug fixes**

- Fixed an `EuiTreeView` JSX Typescript error
([#7452](elastic/eui#7452))
- Fixed a color console warning being generated by disabled `EuiStep`s
([#7454](elastic/eui#7454))

**Accessibility**

- `EuiDataGrid`'s keyboard/screenreader experience has been tweaked to
be more consistent for varying complex data:
([#7448](elastic/eui#7448))
- 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
([#7448](elastic/eui#7448))
CoenWarmer pushed a commit to CoenWarmer/kibana that referenced this pull request Feb 15, 2024
`v92.0.0-backport.0`⏩ `v92.1.1`

---

## [`v92.1.1`](https://github.com/elastic/eui/releases/v92.1.1)

**Bug fixes**

- Minor `EuiDataGrid` cell performance fixes
([elastic#7465](elastic/eui#7465))

## [`v92.1.0`](https://github.com/elastic/eui/releases/v92.1.0)

- Updated `EuiResizableButton` to allow customizing the `indicator`
style with either `handle` (default) or `border`
([elastic#7455](elastic/eui#7455))
- Enhanced `EuiResizableContainer` to preserve the drag/resize event
when the user's mouse leaves the parent container and re-enters
([elastic#7456](elastic/eui#7456))

**Bug fixes**

- Fixed an `EuiTreeView` JSX Typescript error
([elastic#7452](elastic/eui#7452))
- Fixed a color console warning being generated by disabled `EuiStep`s
([elastic#7454](elastic/eui#7454))

**Accessibility**

- `EuiDataGrid`'s keyboard/screenreader experience has been tweaked to
be more consistent for varying complex data:
([elastic#7448](elastic/eui#7448))
- 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
([elastic#7448](elastic/eui#7448))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[EuiDataGrid] Focus behavior on cells that are isExpandable: false and have 1 interactive child
4 participants