cerner / terra-core

Terra offers a set of configurable React components designed to help build scalable and modular application UIs. This UI library was created to solve real-world issues in projects we work on day to day.
http://terra-ui.com
Apache License 2.0
182 stars 167 forks source link

Enhance select option navigation experience on iOS when using VoiceOver #2383

Closed bjankord closed 4 years ago

bjankord commented 5 years ago

Feature Request

Description

When a user on iOS using VoiceOver taps on a select variant with a text entry field, we provide audible instructions to describe how to navigate to the select dropdown options.

The current workflow is as follows:

An enhancement that we are exploring is adding the ability to allow the user to shift the virtual cursor and thus navigate the select dropdown options while focus is on the text input right after the users opens the select dropdown.

The desired enhanced workflow for this use-case would be as follows.

Additional details.

When the dropdown is open, we render it in a portal. This is to allow it to be positioned easily in the DOM and avoid overflow/clipping issues that would arise if the dropdown was positioned relative to the select dropdown triggering element.

By rendering the dropdown in a React portal, it causes some issues when it comes to navigating the select options when using gestures to navigate while using VoiceOver on iOS. To help with this, we've provided instructional text to guide users to tap on/interact with the toggle (chevron) to shift focus to the portalled dropdown when interacting with select variants that allow text entry while using VoiceOver on iOS.

While this works and does allow navigation of the select options, we want to make navigating to the select options more intuitive and allow navigating to the dropdown options via gesture navigation right after the user opens the dropdown when the click on the text input in the select.

If we render the dropdown so that it follows right after the select text input in the DOM it will allow for the virtual indicator to move from the text input to the list of options by double tapping on the text input to open the dropdown, then swiping right to move the virtual indicator into the dropdown option list when using VoiceOver on iOS. However, by rendering the dropdown this way, it is now going to be positioned relative to the triggering element and be bound by the styling rules of it's ancestors in the DOM which creates challenges when trying to render the dropdown so it overflows outside of overflow containers like the modal.

bjankord commented 5 years ago

Options we've explored.

To enable the desired enhanced workflow:

We've explored the following potential solutions:

Keep dropdown in portal, and shift focus to the dropdown as user swipes right.

Unfortunately, when VoiceOver is enabled on iOS, it disables the ability for us to detect the touch events necessary to detect "swipe" events.

Render select dropdown as sibling to select text input.

By doing this, the list options would be the next focusable/interactive element in the DOM following the text input in the select. This would work great allowing the swipe right gesture when the input is focused to move the virtual cursor from the input to the next focusable/interactive element which would be the list of options. The concern with this, and the main reason we haven't implemented this is that by not rendering the dropdown in a react portal and instead rendering it as a sibling, it makes the dropdown constrained by the styles of it's ancestors. This becomes a concern when we want to display the dropdown overflowing outside of a container with overflow: hidden like our modal component.

Dual dropdowns, one sibling dropdown that is visually hidden, one portal dropdown that is the visual representation

This option requires rendering 2 dropdowns that are mirrors of each other. One to provide a visual representation and one to provide a representation that works ideally with VoiceOver on iOS. This has the benefit of allowing the natural focus shift from text input to next focusable/interactive element by focusing to the sibling dropdown and having that be visually hidden. And then keeping the portal based dropdown as a visual representation. With this approach, there is some concern of trying to mirror/layer the two dropdowns as well as a performance concern by introducing 2 dropdown elements in the DOM.

PR for this approach: https://github.com/cerner/terra-core/pull/2382

bjankord commented 5 years ago

It may be worthwhile to explore rendering select dropdown as sibling to select text input some more to see exactly how the pain points of not using a portal for the dropdown show up and if there is any way to mitigate those as this approach allows the most ideal usage of the select when using VoiceOver on iOS with minimal code needed to be tailored specific to the screen reader.

StephenEsser commented 5 years ago

There would likely be some cosmetic impacts, but other potential option proposed by @dkasper-was-taken a while back was to portal both the input and the dropdown. This would allow them to be siblings, but would introduce some strange behavior when the page was scrolled.

bjankord commented 5 years ago

Talked with @StephenEsser and @dkasper-was-taken about this more and we've received designs from UX to open the dropdown as a modal on mobile devices. With this we can render the input and list of options as sibling elements in the DOM in the modal popup which will enable the desired VoiceOver virtual indicator/cursor navigation on iOS devices.

bjankord commented 5 years ago

@dev-cprice has put together a tech design to implement the responsive modal/dropdown for the select options here: https://github.com/cerner/terra-core/issues/2405

bjankord commented 5 years ago

Wanted to note another pattern I'd seen in the wild. Khan Academy has a multi-select where when you open it, the input is in the dropdown. This allows the input and the options to be siblings in the DOM.

Screen Shot 2019-06-12 at 12 51 58 PM

bjankord commented 5 years ago

We've talked through this and landed on a solution of rendering the input within the portal along with the options.

This solves the issue we've seen on iOS when using VoiceOver, it should also allow us to simplify some of the logic / rendering for other screen readers as well.

bjankord commented 4 years ago

Closed via #2658