Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot focus on elements inside (some) shadow containers and <iframe> elements. #131

Closed
duhrer opened this issue Dec 15, 2023 · 10 comments
Closed
Labels
bug Something isn't working

Comments

@duhrer
Copy link
Contributor

duhrer commented Dec 15, 2023

In recent testing of the gamepad navigator with a page from the FLOE project, I discovered a range of unreachable elements:

  1. Elements in "closed" shadow roots (such as video elements).
  2. Elements in iframes (such as UIO on that page).

I was able to special-case video elements (see #132), but we still don't have an approach for closed shadow roots or <iframe> elements.

Given the CORS concerns and sandboxing in modern browsers, I'm not sure we're going to be able to address the concerns with <iframe> elements.

Pretty sure we won't be able to work with a "closed" shadow root either.

@duhrer duhrer added the bug Something isn't working label Dec 15, 2023
@duhrer
Copy link
Contributor Author

duhrer commented Dec 15, 2023

NPM helpfully provides this comparison of similar libraries.

I also searched npm, and found tabbable, which seems well maintained.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 16, 2023

So, I forked ally and applied the shadow fix in this pull request. It still doesn't work, so there seems to be something else going on. I am explicitly testing with the same FLOE page.

Looking at which "tabbables" ally detects, it detects the video itself as tabbable, but not the sub-elements. I need to see what happens in code when I'm either right before or right after the video element. Onscreen, it just seems to wrap around. It may be that there's no focus highlight on the video itself, and that there are no sub-elements found to focus on.

I also notice that on that page, I can't reach the UIO controls (other than the "show/hide" button), I need to understand that as well. With keyboard navigation, it all "just works", there may be a few issues to unpack.

I suspect I'll end up making my own detection algorithm, but for now I need to start by picking apart the problems on a test page. I'll make a manual test fixture for now, including:

  1. An "open" shadow root with tabbables inside.
  2. A "closed" shadow root with tabbables inside.
  3. A video element.

Once I understand what's wrong, I can convert that page to a proper test fixture and use it to test either a library or our own approach.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

I constructed a test fixture as described above. With a keyboard and tab/shift+tab, I can reach:

  1. Non-shadow content in the body of the document
  2. Content within an "open" shadow root
  3. Content within a "closed" shadow root
  4. A video element that has controls
  5. The controls within that element
  6. Content within an <iframe>

With tab / shift + tab, I cannot reach:

  1. A video element with no controls

As a side note, you can right click a video element without controls, show the controls, and then tab to it. This suggests that the display of controls is something the user is allowed to change, so perhaps we can automatically enable controls for any video elements we find (as a configurable preference).

Let's now compare tab navigation with ally's detection of "tabbables", which finds the following on the same page:

  1. Non-shadow content in the body of the document
  2. Content within an "open" shadow root
  3. The outer container of a video element with controls

It does not detect:

  1. Content within a "closed" shadow root
  2. The controls within a video element with controls
  3. Content within an <iframe>

The test fixture now clearly demonstrates the two problems observed on the FlOE page.

My next step is to see what's visible in the DOM, for:

  1. The <video> element with controls
  2. The <video> element without controls
  3. The <iframe> element
  4. The "closed" shadow root container

I should also see if ally's "focusable" detection (or any of their other modes) does any better.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

First, the details of what ally detects. With the "quick" strategy, ally detects:

  1. Non-shadow content in the body of the document
  2. The outer container of the video element with controls

With the "strict" strategy, ally detects:

  1. Non-shadow content in the body of the document
  2. The outer container of the video element with controls
  3. Content in an "open" shadow root

With the "all" strategy, ally detects:

  1. Non-shadow content in the body of the document
  2. The outer container of the video element with controls
  3. Content in an "open" shadow root (including all of our hidden modal buttons!)

Although I suspected as much from previous manual testing, it's good to confirm and document that none of ally's strategy for detecting tabbables does what we need.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

Ally's focusable method detects the following using the "quick" strategy:

  1. Non-shadow content in the body of the document
  2. The outer container of the <video> element with controls
  3. The outer container of the <iframe>

Their "strict" strategy detects:

  1. Non-shadow content in the body of the document
  2. The outer container of the <video> element with controls
  3. The outer container of the <iframe>
  4. Content within an "open" shadow root (not including hidden content).

Their "all" strategy detects:

  1. Non-shadow content in the body of the document
  2. The outer container of the <video> element with controls
  3. The outer container of the <iframe>
  4. Content within an "open" shadow root (including hidden content!).

So, their "focusables" method doesn't do what we need either.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

In testing this, I discovered that clicking a video with our click action does nothing, which I've documented as #132.

@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

OK, we'll have to handle <video> elements with special-casing in #132, the "user agent" mode shadow root is totally opaque, we can't see anything.

This issue should now focus on <iframe> content and closed shadow roots.

@duhrer duhrer changed the title Cannot focus on elements inside (someone else's) shadow container. Cannot focus on elements inside (some) shadow containers and <iframe> elements. Dec 18, 2023
@duhrer
Copy link
Contributor Author

duhrer commented Dec 18, 2023

OK, with the fixes for #132, I'm going to leave this one open and update the summary to make it clearer where the hard limits of our current approach are.

@duhrer
Copy link
Contributor Author

duhrer commented Jan 30, 2024

This should be broken out as we probably have an approach for iframes.

@duhrer
Copy link
Contributor Author

duhrer commented Jan 30, 2024

I'm closing this out for now in favour of #155, as most of the video issues were addressed in #132.

@duhrer duhrer closed this as completed Jan 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant