web-components icon indicating copy to clipboard operation
web-components copied to clipboard

[grid] Keyboard focus does not stay in sync with VoiceOver cursor

Open juuso-vaadin opened this issue 3 years ago • 8 comments

What is the problem?

Issue

When a table element becomes focused, VoiceOver prompts to use Control+Option+Arrow keys to navigate the cells. The keyboard focus is independent from VoiceOver cursor which leads to two cells being "focused" at same time.

For regular Grid this is not much of an issue. In GridPro, user can move the VoiceOver cursor to a cell and expect that cell to become editable when hitting Enter key. What really happens is that the cell with keyboard focus will become editable.

https://user-images.githubusercontent.com/19607782/167617169-17e7f28e-55d2-40be-be7a-0ef2da8eabfe.mov

Solution proposal

For expected behaviour, see example 2 on page https://www.w3.org/TR/wai-aria-practices/examples/grid/dataGrids.html#

The example above is not without issues either. Moving the VoiceOver cursor to interactive cell will automatically move the keyboard focus to the element which is expected. Moving the VoiceOver cursor to a non-editable cell will not remove the keyboard focus which stays in the previously focused interactive element.

https://user-images.githubusercontent.com/19607782/167617193-f692e40b-06af-460f-b354-f1df42b8c4b9.mov

Browsers

  • [X] Chrome
  • [ ] Firefox
  • [X] Safari
  • [ ] Safari on iOS
  • [ ] Edge

Screen Readers

  • [ ] None
  • [ ] NVDA
  • [ ] JAWS
  • [X] VoiceOver on MacOS
  • [ ] VoiceOver on iOS

juuso-vaadin avatar May 10 '22 11:05 juuso-vaadin

Affecting both Vaadin 14 and latest.

yuriy-fix avatar Jun 27 '22 09:06 yuriy-fix

Tested with VoiceOver on Chrome and Safari and the main problem is the fact that there is no keydown event fired when navigating grid cells using arrow keys. This is not specific to vaadin-grid, happens in ARIA examples as well:

Normal behaviour

There is a keydown for each key press.

https://user-images.githubusercontent.com/10589913/176142645-46524984-0414-47d6-b378-6d20c533231f.mp4

VoiceOver enabled

No keydown event fired at all 😕

https://user-images.githubusercontent.com/10589913/176142688-220309d3-cc44-41da-9af1-e8f94daf954b.mp4

web-padawan avatar Jun 28 '22 09:06 web-padawan

After some investigation, it turns out that VoiceOver does fire focus events for buttons inside table<table> cells when using Ctrl + Option + arrow keys. In ARIA example it's done using <span role="button" tabindex="-1">.

However, when focusing cells themselves (e.g. elements like <td tabindex="-1">), the focus event does NOT fire.

https://user-images.githubusercontent.com/10589913/176185389-7be4ffec-129c-4a51-87a2-523173c50623.mp4

I will continue investigating whether it would be possible to update logic for vaadin-grid-pro as follows:

  • Do not set tabindex on cell elements for cells created by vaadin-grid-pro-edit-column,
  • Have an element inside vaadin-grid-cell-content use role="button" + tabindex instead.

web-padawan avatar Jun 28 '22 13:06 web-padawan

I will continue investigating whether it would be possible to update logic for vaadin-grid-pro as follows

Tested this in #4114 and the resulting change appears to be quite intrusive:

  1. There are many parts in the code that need to be adjusted (and tested) to detect whether to focus cell or its content,
  2. Currently, the cell content can be smaller than the cell itself. This causes extra problems when detecting the focusin event location, see https://github.com/vaadin/web-components/pull/4114#pullrequestreview-1027545626

Also tested an alternative approach inspired by vaadin-crud-edit-column. It's less intrusive than the previous approach: in fact, it's about rendering one extra element in the cell content, without touching existing tabindex attributes. However, there is a problem described in https://github.com/vaadin/web-components/pull/4114#issuecomment-1175058087: with VoiceOver + Chrome, it only works partially.

Taking the above into account, I don't see an easy way to fix this issue without significant changes in the grid logic.

web-padawan avatar Jul 05 '22 13:07 web-padawan

Under certain circumstances, the issue can be also reproduced with vaadin-grid-selection-column:

  1. Focus a first cell with checkbox by pressing Tab twice
  2. Then navigate away to Ctrl + Option + Arrow Down
  3. Note that focus outline is no longer in sync with VoiceOver outline
  4. Press Space to select a checkbox in the wrong cell

https://user-images.githubusercontent.com/10589913/177726161-2c0ad886-5666-4206-a483-36e9f2223777.mp4

web-padawan avatar Jul 07 '22 08:07 web-padawan

Research summary

Based on my findings, the issue can’t be easily fixed without introducing quite significant changes to vaadin-grid web component, just to make sure VoiceOver fires focus event every time the editable cell receives focus with Ctrl + Option + Arrow Up and other arrow keys (which is how the table navigation mechanism works in VoiceOver).

In addition to vaadin-grid-pro, the VoiceOver issue also affects vaadin-crud where the problem happens only when navigating vertically between cells in edit column. Even though edit column contains accessible buttons, VoiceOver fails to focus them properly. See https://github.com/vaadin/web-components/issues/4134#issuecomment-1176290856 for some problematic code that causes it (with no obvious reason).

The only solution that seems to work reliably is to change tabindex from table cells (<td> in Shadow DOM) to cell content elements (<vaadin-grid-cell-content> in light DOM). This is how the linked ARIA example for editable grid works.

So, the whole keyboard navigation logic would need to be adjusted to support a special mode for columns like vaadin-grid-pro-edit-column, vaadin-crud-edit-colum and vaadin-grid-selection-column (also its Flow version).

IMO the proper fix for this would be to add a new API to vaadin-grid-column and then update all the builtin columns with focusable content to use this API. This work and testing in different screen readers might take considerable effort.

Conclusion

The issue is currently on hold. We will get back to it in the upcoming weeks and discuss with other team members to decide how to tackle it. Our end goal is to ensure all of our components are accessible, so we will do our best to fix this.

Until then, my recommendation is to use arrow keys to navigate the grid cells when using VoiceOver on MacOS, without holding Ctrl + Option. This is needed to avoid problem with keydown events not being fired.

web-padawan avatar Jul 07 '22 08:07 web-padawan

Some more findings from researching a possible solution (which is still quite incomplete).

Currently, keyboard navigation is based on the assumption that keyboard focus always moves within Shadow DOM:

https://github.com/vaadin/web-components/blob/4fb709e15e78a2e1d12c7f38e5a28bfa7f028442/packages/grid/src/vaadin-grid-keyboard-navigation-mixin.js#L87-L89

When we try to move focus to vaadin-grid-cell-content, the above assumption is no longer true: the element is in light DOM, so technically the focus leaves vaadin-grid. Therefore, focusout and focusin listeners are invoked.

As a result, the logic related to pressing Tab to exit the grid becomes broken: we call this.$.focusexit.focus() and it fires the focusin event, because native focus enters the Shadow DOM. So the focus gets stuck inside the grid cell content.

web-padawan avatar Jul 20 '22 13:07 web-padawan

Looks like we can make VoiceOver work correctly using the following DOM structure:

<td>
    <div role="button" tabindex="-1">
      <slot name="vaadin-grid-cell-content-12"></slot>
  </div>
</td>

This solution is less intrusive compared to the initial one, because focus remains in Shadow DOM, so the problem described in the above comment would not happen. Therefore, the amount of changes to make should be smaller.

Here is a new prototype branch: https://github.com/vaadin/web-components/compare/wip/grid-cell-focus Tested it in VoiceOver and it works as expected in both Chrome and Safari: focus is moved to <div role="button">.

web-padawan avatar Jul 20 '22 15:07 web-padawan