elastic / eui

Elastic UI Framework 🙌
https://eui.elastic.co/
Other
6.08k stars 829 forks source link

[AriaToolbar] component #3500

Open myasonik opened 4 years ago

myasonik commented 4 years ago

Preamble

There are 3 focus strategies: the default one (tabbing works as expected), roving tabindex, and aria-activedescendant.

The default one just works so there's nothing for us to do. aria-activedescendant is pretty rare so let's not worry about it at the moment. But roving tabindex does come up with decent frequency so I'd like to explore creating a reusable pattern (component? util? hook?) for quickly implementing it. Ideally it'd be exportable so consumers as well as EUI could benefit from it.

Summary

With several tab-heavy, discrete components we want to keep the keyboard experience streamlined. Taking Kibana as an example, tabbing through the app can become an arduous and long process depending on the page.

One way to streamline this is a roving tabindex. All the tabbable items of a component get tabindex=-1 except the first one which is at tabindex=0. Once you're on the first element, you can use arrow keys to move your focus between the tabbable items. Pressing tab again moves you out of the component. Tabbing back into it (e.g., shift+tab) returns can optionally return you to either the first tabbable item again or return you to the same one when you exited (depending on whichever makes most sense for the component).

ARIA spec for reference

Technical considerations

  1. Should optionally reset to first item or last item to be focused
  2. How many axises do we want to support? (Only 1-axis would be simpler for sure, but 2-axis use cases also exist.)
  3. Should only be allowed on specific aria roles (I can make a list of which once we get to this.)

Design/UX considerations

  1. It can sometimes be unexpected when the tabbing strategy switches. Do we want any sort of visual indicator? (I've seen a little arrow keys icon popup on the page sometimes for when roving tab focus is in place. Could also do something with custom focus states on either the wrapping component or each tabbable element. Probably other ideas out there as well.)

    All that said, solving this isn't a big deal in my opinion because the cost of not knowing is pretty low. (A user may tab past the component but should always be able to tab back and arrow keys are a common alternative so there shouldn't be any teaching required.)

  2. Some things are assumed to be one axis but can overflow to more line. In those cases, it's a toss up rather focus should support 2-axis arrow navigation as well. Assuming everything is technically feasible, what would we want to do? (For example, a toolbar that spans two lines.)

Examples in EUI today

  1. DataGrid* is a great example of 2-axis roving focus (role=grid)
  2. BottomBar and ControlBar should support x-axis roving (role=toolbar)
  3. ButtonGroup with more than 3 buttons should support x-axis roving (role=toolbar)
  4. TreeView should support y-axis roving (role=tree)
  5. Tabs with more than 3 tabs should support x-axis roving (role=tablist)
  6. Pills inside a ComboBox should support x-axis roving (role=list, I think...)
  7. FilterGroup with more than 3 FilterGroupButton items should support x-axis roving (role=toolbar, I think...)
  8. Misc other "toolbars" (e.g., above the DataGrid, above the Markdown)
cchaos commented 3 years ago

I think this issue has gone stale because we're not sure what the actual course of action is here.

myasonik commented 3 years ago

Sorry for the length 😬

TLDR: A component (or, potentially, a custom React hook) that finds all of its tabbable children and puts tabindex=-1 on all except the first one which is set to tabindex=0. Once you're on the first element, you can use arrow keys to move your focus between the tabbable items. Pressing tab again moves you out of the component. Tabbing back into it (e.g., shift+tab) returns focus either to the first tabbable item or to the same item where you exited (should be configurable).

github-actions[bot] commented 3 years ago

👋 Hey there. This issue hasn't had any activity for 180 days. We'll automatically close it if that trend continues for another week. If you feel this issue is still valid and needs attention please let us know with a comment.

github-actions[bot] commented 10 months ago

👋 Hi there - this issue hasn't had any activity in 6 months. If the EUI team has not explicitly expressed that this is something on our roadmap, it's unlikely that we'll pick this issue up. We would sincerely appreciate a PR/community contribution if this is something that matters to you! If not, and there is no further activity on this issue for another 6 months (i.e. it's stale for over a year), the issue will be auto-closed.

JasonStoltz commented 5 months ago

We revisited this in a grooming meeting recently. We feel there is a lot of value here, specifically in splitting the DataGrid's toolbar into it's own component. Many folks use the DataGrid just for it's tool bar.