React-virtualized: [FlexTable] Disable tabindex on rows

Created on 22 Jul 2016  路  7Comments  路  Source: bvaughn/react-virtualized

Would it be possible to have an option to disable the tabindex on rows like you can disable the tabindex on the complete FlexTable by using tabIndex={null}?

Most helpful comment

@bvaughn sorry to bring this back from the dead, but I've just run into it trying to make my app accessible, and I don't think you're totally right. Right now, I don't agree the current tabindex behaviour is a11y friendly.

https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets is a good guide to this. The relevant snippet:

For grouping widgets such as menus, tab panels, grids, or tree views, the parent element should be in the tab order (tabindex="0"), and each descendent choice/tab/cell/row should be removed from the tab order (tabindex="-1"). Users should be able to navigate the descendent elements using arrow keys.

This references the WAI-ARIA Authoring Practices, which has a lot more detailed content on this. There's a few relevant points in there, but it very closely agrees with the MDN summary, e.g. under 'Fundamental Keyboard Navigation Conventions':

A primary keyboard navigation convention common across all platforms is that the tab and shift+tab keys move focus from one UI component to another while other keys, primarily the arrow keys, move focus inside of components that include multiple focusable elements.

Right now, because tabindex=0 is set on all rows within the table, these recommendations aren't followed, and indeed are impossible to follow. Every single row of the table, and the table itself, are treated as top-level UI components, which isn't correct and is hard to use.

Instead, the table should have tabindex=0, rows within should have tabindex=-1, and JS should be used to ensure that the arrow keys manage focus within those rows correctly. MDN has two recommended approaches to do exactly that: https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets#Managing_focus_inside_groups.

If you want to really dig into it, there's an 'interactive tabular data' section in the ARIA doc that exactly describes this case and covers the suggested behaviour & keyboard shortcuts in full: https://www.w3.org/TR/wai-aria-practices-1.1/#grid

For now I'm going to fix this in my app by replacing the table rowRenderer to fix tabindexes, and managing focus with onKeyDown. Would you be interested in a PR to apply that change here too?

All 7 comments

What's the use-case?

Initial thought is that the API for this would be a bit awkward, since other click/tab things are for the _whole_ table.

Sorry, I meant for all rows, not a specific one.

tabIndex is only added to a row if you have mouse-events registered. This is an important for a11y (usability). Without it, keyboard-only users can't focus-on (can't "click") the rows. I don't think this is something I should make configurable.

I think this is not something a library should decide for me. I understand your intention but there are cases where this is not the wanted behaviour.

It's not possible for react-virtualize (or any library) to implement every feature that people suggest. Each feature ads complexity (even if only a little) which increases the burden of maintenance. Also once a feature is in a library, there's a much higher bar for removing it. (It requires a major release; people may complain that they've come to depend on the feature. etc)

As a maintainer, I try to choose configurable options that I think are useful to a significant percentage of users and I try to choose reasonable defaults for the rest. In this case, I think choosing a default that is a11y-friendly is the right choice.

If you would like to submit a PR with a proposal for how to implement this I would be happy to review it, but I may decide not to merge it (for the reasons I mentioned above).

All this being said, FlexTable and VirtualScroll are both just high-order components that decorate a Grid. Neither are meant to be as flexible or full-feature as Grid. They're just intended to be a convenient way to create a certain _type_ of grid layout. If you don't like their defaults, you can always fall back to using a Grid.

I'm going to close this issue for now because I don't intend to take any action on it. We can continue to chat here though. (I'll still see and respond to your messages.) If you'd like to make a case for why this functionality is important to your application, I will give it consideration.

@bvaughn I have two tables side by side in some type of container with two search fields above. I want that the user is to be able to switch with Tab between these search fields. There should be at the maximum the focus-step to the table between these two.
Additionally the table itself implements an onRowClick and an onRowDoubleClick. The double click action is the main action. I want to implement a keyboard control with the arrow keys (up and down) for the onRowClick action and a Space or Enter for the onRowDoubleClick action. But this is not possible if the tabIndex is active on the rows. The selection (or focus) that is done by the arrow keys or the click handler is a Redux action. I want to be able to control the focus from outside by actions.

@bvaughn sorry to bring this back from the dead, but I've just run into it trying to make my app accessible, and I don't think you're totally right. Right now, I don't agree the current tabindex behaviour is a11y friendly.

https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets is a good guide to this. The relevant snippet:

For grouping widgets such as menus, tab panels, grids, or tree views, the parent element should be in the tab order (tabindex="0"), and each descendent choice/tab/cell/row should be removed from the tab order (tabindex="-1"). Users should be able to navigate the descendent elements using arrow keys.

This references the WAI-ARIA Authoring Practices, which has a lot more detailed content on this. There's a few relevant points in there, but it very closely agrees with the MDN summary, e.g. under 'Fundamental Keyboard Navigation Conventions':

A primary keyboard navigation convention common across all platforms is that the tab and shift+tab keys move focus from one UI component to another while other keys, primarily the arrow keys, move focus inside of components that include multiple focusable elements.

Right now, because tabindex=0 is set on all rows within the table, these recommendations aren't followed, and indeed are impossible to follow. Every single row of the table, and the table itself, are treated as top-level UI components, which isn't correct and is hard to use.

Instead, the table should have tabindex=0, rows within should have tabindex=-1, and JS should be used to ensure that the arrow keys manage focus within those rows correctly. MDN has two recommended approaches to do exactly that: https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets#Managing_focus_inside_groups.

If you want to really dig into it, there's an 'interactive tabular data' section in the ARIA doc that exactly describes this case and covers the suggested behaviour & keyboard shortcuts in full: https://www.w3.org/TR/wai-aria-practices-1.1/#grid

For now I'm going to fix this in my app by replacing the table rowRenderer to fix tabindexes, and managing focus with onKeyDown. Would you be interested in a PR to apply that change here too?

Was this page helpful?
0 / 5 - 0 ratings