bitwarden / clients

Bitwarden client apps (web, browser extension, desktop, and cli).
https://bitwarden.com
Other
8.8k stars 1.15k forks source link

Accessibility: Browser - missing focus handling on most page/view transitions #3676

Open patrickhlauke opened 1 year ago

patrickhlauke commented 1 year ago

Steps To Reproduce

  1. Use a screen reader (e.g. NVDA on Windows)
  2. Open the extension
  3. Go to Vault
  4. Use keyboard to set focus to a vault item (or do it in a folder/collection)
  5. The item opens

Expected Result

When the view transitions to the item, focus should explicitly be moved to the top/start of the new view (either on the "Back" button, if present, or something like the new view's main heading in the header bar)

Actual Result

Focus is left completely unhandled. Depending on browser/assistive technology, the result can be that focus goes to an arbitrary element in the new view.

In the case of Chrome/NVDA, focus remains on a "ghost" version of the control that was just activated (and that button is now announced again). Subsequent Tab goes to the top left control in the view - so it's not too bad. However, using the cursor/reading keys when landing on the new view, reading starts from a point that is roughly in the same visual location as the last known good focus position (the "ghost" button), rather than the start of the page.

This behaviour appears in various other locations - when going to the generator history, or sub-views in the options, etc.

There's also related cases with the Generator and Settings buttons in the bottom tab bar ... once activated, focus remains on them rather than jumping to the top of the screen.

Screenshots or Videos

Video recording of some of the places where focus is not properly set after a page/view transition - using Chrome/NVDA and navigating using Tab key and Enter

https://user-images.githubusercontent.com/895831/193679651-a4a82720-4577-4def-adfb-113160c5ba93.mp4

Another video, specifically showing how once you get to a view and the "ghost" button is re-announced, using cursor/reading keys starts reading arbitrarily from the last known visual focus location rather than the top of the page.

https://user-images.githubusercontent.com/895831/193679881-4ae3c3e9-e586-40d5-a77e-e1a8a1a20064.mp4

Additional Context

For SPAs, on a dynamic page transition, focus should be explicitly handled.

See https://angular.io/guide/accessibility#focus-management-after-navigation. Note that the concept is not limited to Angular - similar advice is given to React devs https://egghead.io/lessons/react-appropriately-set-the-focus-on-each-page-load-of-a-web-application and even plain vanilla JS authors. Whenever you dynamically change a page and/or "yank" the currently focused element away, you must explicitly set it somewhere else of risk being at the mercy of the browser/screen reader error correction heuristics, as outlined above for NVDA for instance.

Decide what the best initial focus/reading order location is for each view, and once it's displayed set focus explicitly to it.

To set focus to an interactive control like a button, it'll be sufficient to trigger the .focus() method. If it's a static element, like a <div>, <h1>, or similar, you will also need to add tabindex="-1" to that element to signal that it's programmatically focusable (without adding it to the actual focus/Tab cycle unnecessarily)

Operating System

Windows

Operating System Version

10

Web Browser

Chrome

Browser Version

No response

Build Version

2022.9.1

tangowithfoxtrot commented 1 year ago

Thanks for reporting, @patrickhlauke!

I've confirmed the behavior and marked this as being reproducible internally.