Open Bug 1708261 Opened 4 years ago Updated 3 months ago

focusring not shown in dialogs when opened with keyboard

Categories

(Toolkit :: UI Widgets, defect, P3)

Desktop
All
defect
Points:
3

Tracking

()

Accessibility Severity s3

People

(Reporter: mconley, Unassigned, NeedInfo)

References

(Blocks 1 open bug)

Details

(Keywords: access, Whiteboard: [proton-cleanups])

In bug 1704882, we're the checkbox in some of our modal dialogs is being focused when the dialog opens, but we're intentionally suppressing the focus ring per UX and Product request.

This has the drawback of hiding the focus ring even if the user had used a keyboard to get to the dialog, which isn't great, a11y-wise. We should try to figure out the right strategy for hiding the ring here.

Priority: -- → P3
See Also: → 1709050
Points: --- → 3
OS: Unspecified → All
Hardware: Unspecified → Desktop
Whiteboard: [proton-cleanups] → [proton-cleanups][access-s3]
See Also: → 1763470

For the context that not showing a focus indication especially after the context changes (ie. a dialog is opened) is very confusing for sighted keyboard users, because it prevents them from identifying the position of the focus. Unfortunately, there are too many examples of the focus being left on some removed element or somewhere under the overlay out there in Internet, users are not expecting the focus to be actually on a dialog, unless they can see it.

Besides being a dark usability pattern by itself, this is also a direct violation of the WCAG 2.1 Success Criterion 2.4.7 Focus Visible, as well as 2.1.1 Keyboard and 3.2.1 On Focus, which are all covered under explicit F55 Failure.

When a button is added on-screen by the design, it’s purpose for a user to use it, but keyboard users may avoid doing it, because the risk of activating something that they do not know may bring an unexpected consequences and even returning the focus back to this button may make usage of the dialog too cumbersome for them, ie. for a switch user with limited dexterity for whom each keypress may take up to a minute.

See Also: → 1765143

I looked into changing the dialog's open method to add a parameter that skips the focus ring flag for keyboard events, but there's such an immense distance between the user events and the open method. The average code path has like 20+ function calls between the last call aware of the event and the final call that advances the focus. Also, a lot of the users actually invoke dialogs on command events, not on click or keypress events, so that complicates things further. Maybe there's a lower level way to do this that doesn't occur to me. Would it be crazy to pass the event.type all the way to the SubDialog constructor?

(In reply to Shane Hughes [:aminomancer] from comment #2)

I looked into changing the dialog's open method to add a parameter that skips the focus ring flag for keyboard events, but there's such an immense distance between the user events and the open method. The average code path has like 20+ function calls between the last call aware of the event and the final call that advances the focus. Also, a lot of the users actually invoke dialogs on command events, not on click or keypress events, so that complicates things further. Maybe there's a lower level way to do this that doesn't occur to me. Would it be crazy to pass the event.type all the way to the SubDialog constructor?

If it's actually 20 function calls that doesn't sound like fun, no. I think it's often less, e.g. (first example I looked at, honestly!):

https://searchfox.org/mozilla-central/rev/25ec642ed33ca83f25e88ec0f9f27e8ad8a29e24/browser/components/preferences/main.js#1357-1359

is an event handler for the command event attached at https://searchfox.org/mozilla-central/rev/25ec642ed33ca83f25e88ec0f9f27e8ad8a29e24/browser/components/preferences/main.js#467 . So we can simply add an e param to showLanguages and then check the event's sourceEvent to see if it was keyboard-generated.

I'd find it useful for context in this bug what the 20-stackframe case is that you looked at? :-)

Even if most cases use fewer stackframes though, it'd still be annoying to update all the callsites though, and easy to forget to do it for new ones (or miss callers) because it effectively becomes "opt in" for the consumer. Given the seriousness described in comment #1 we might want something that's more "automatic", perhaps with an additional opt-in for complex cases (e.g. dialogs opening asynchronously)

I wonder if we could use something similar to hasValidTransientUserGestureActivation, which is a (privileged, ie not web-visible) property on document. If we track if the last event was keyboard or mouse-based, that would likely be sufficient in the 99.99% case (might in theory miss cases where opening the dialog is async and the user opens with keyboard and then clicks with the mouse, but that seems veeeeery edge-casey.

The other option, if we can realistically pass information and we don't like the edgecase I just described, would be to enforce that callers that open dialogs pass either "click" or "keypress" or something and just refuse to open the dialog without, to enforce that consumers consider this.

Flags: needinfo?(shughes)
Severity: -- → S3
Type: task → defect
Summary: Figure out the right focus / focusring strategy for modal dialogs → focusring not shown in dialogs when opened with keyboard on Windows

So we could make SubDialog.open take the triggering event which seems to be fairly simple, it would require changing ~40 call sites on a quick search. Updating hasValidTransientUserGestureActivation looks like we'd probably need someone who has a better understanding of our C++ code than myself

Accessibility Severity: --- → s3
Whiteboard: [proton-cleanups][access-s3] → [proton-cleanups]
Duplicate of this bug: 1915358
Summary: focusring not shown in dialogs when opened with keyboard on Windows → focusring not shown in dialogs when opened with keyboard
You need to log in before you can comment on or make changes to this bug.