Workday / canvas-kit

Development kits to implement UI following the Workday Canvas Design System (https://canvas.workday.com/). See our Component Storybook -
https://workday.github.io/canvas-kit/
Apache License 2.0
301 stars 221 forks source link

a11y: Make scrollable sections keyboard-focusable #1699

Open ahayes91 opened 2 years ago

ahayes91 commented 2 years ago

🚀 Feature Proposal

Scrollable sections in the UI should have a tabindex to allow keyboard-only users to navigate to them and scroll to access any static text. https://dequeuniversity.com/rules/axe/3.5/scrollable-region-focusable

Suggested requirements (based on the same feature we built into Workday Learning):

When there is overflow content, the container for that content requires

When there is no overflow content, the containing div for the content doesn't need any of the above.

We achieved this in Learning modals by using a resize observer that conditionally adds the role=group, aria-labelledby and tabindex if it detects overflow in the scrollable area.

Motivation

As above and in https://dequeuniversity.com/rules/axe/3.5/scrollable-region-focusable

Example

This is probably most relevant for Modal components. https://canvas.workdaydesign.com/components/popups/modal/#body-content-overflow is an example. When you minimise the screen and use keyboard only to navigate to the modal, you can’t navigate to the scrolling section and see the overflow content.

Speaking to @NicholasBoll about this internally, he had some comments:

This seems like a common enough issue and there should be a scrollable container component that has these properties.

The deque article doesn't mention the necessity for semantic meaning of the tabstop. It is a group labelled by something, but it doesn't give any semantic meaning why that relationship is necessary. Is it okay if the role=group always exists for possible overflow content that doesn't have specified keyboard navigation (for example, overflowed menus already have keyboard support)? Meaning should it be required to add a resize observer for all overflowed content to conditionally add a role=group?

It makes sense for us to create a scrollable overflow component (or at least an elemPropsHook to add functionality to any component) that is aware of a model with an id state property that can accomplish what you have. If scrolling content needs keyboard accessibility everywhere, this functionality should be easy to integrate and the default everywhere that's applicable

mathalete commented 2 years ago

There’s a design aspect to this too in that a focus outline needs to be accounted for when that container has overflow and has keyboard focus, and a visual treatment would help communicate visually there is actually overflow.

Low vision users have not perceived the browser generated scrollbars that are shown when a container has overflow in a recent study that included tables with overflow - so there’s an opportunity to improve this experience.

For compliance any visual treatment to communicate overflow would need to exceed the non-text contrast SC.

NicholasBoll commented 1 year ago

Here's my idea:

We'll have to watch out for overflow-limiting focus rings. This shouldn't be much of a problem usually unless we have scrollable areas inside of scrollable areas. We had this problem with Modal body being overflowed with buttons