fluid-lab / gamepad-navigator

GSoC 2020 project
Other
6 stars 10 forks source link

Visible focus is not shown for all elements. #161

Closed duhrer closed 4 months ago

duhrer commented 4 months ago

I've been occasionally seeing issues where focus indicators would be visible for some but not all elements. It was clear that focus was still changing, you could see the URL of a focused link in the footer of the browser window, but the focused element didn't have any styles. Hitting keyboard generally "unsticks" things and focus is visible on all elements.

I now have a consistent way to reproduce the stuck state in at least one circumstance:

  1. Open a new window (with the Google search).
  2. Enter text in the search field.
  3. Navigate to the search button and click it.
  4. Use bumper navigation to try and reach the search results.

The buttons for the type of search ("images", "shopping", etc.) have focus styles, but when you reach the results, no focus styles are applied, even though it's clear that focus is changing, and you can click the focused search result.

duhrer commented 4 months ago

I've seen variations on this where the modals would lose focus until you reload or hit a tab on the keyboard as well, but I can't consistently reproduce that.

duhrer commented 4 months ago

Although sadly we can't operate the code with the Gamepad Navigator because it's in an iframe (see #155), this CodePen illustrates what I think is the core of the problem, namely that :focus-visible styles stop being applied if there's not actual keyboard input.

duhrer commented 4 months ago

There are a few threads like this, but here's an example Stack Overflow thread that suggests working around the problem by making the element editable before focusing, and then changing it back after.

duhrer commented 4 months ago

Looks like there is a configuration option to use with focus() to indicate that visible focus should be triggered.

duhrer commented 4 months ago

I can't get any of the hacks or the optional parameter to work.

Changing the browser preferences does work, i.e. visit chrome://settings/accessibility, then toggle "Show a quick highlight on the focused object".

Depending, maybe we can detect if that's not set and advise people to change it.

duhrer commented 4 months ago

Looks like an extension can change this using the accessibilityFeatures parts of the web extensions API.

One option would be to add actions to enable/disable that setting, or perhaps one to toggle the setting.

duhrer commented 4 months ago

The documentation suggests that the permission is only visible in Chrome OS, which I confirmed by adding the read permission and checking the service worker in the debugger;

duhrer commented 4 months ago

There is also an IME API for Chrome OS that would let us act a lot more like a keyboard, but you can't even try that with a Chrome extension.

duhrer commented 4 months ago

I also added embedded styles for :focus:not(:focus-visible), which show up if you toggle focus (but not focus-visible) in the dev console, but don't help with the problem.

duhrer commented 4 months ago

The focusVisible option passed as a parameter to the focus method is apparently only supported in Firefox at the moment.

duhrer commented 4 months ago

I also added embedded styles for :focus:not(:focus-visible), which show up if you toggle focus (but not focus-visible) in the dev console, but don't help with the problem.

Looks like I had to be more aggressive. If I just changed the outline-style and outline-color, an element with an outline shorthand property would win.

If I inline an outline shorthand property for elements which are focused but not focus visible, I get outlines. Now we just need to add this as a preference.

duhrer commented 4 months ago

This still doesn't work, it won't consistently pick up the styles. My latest idea is to add an overlay that partially obscures everything but the focused element and that has a border to take the place of the outline. This might be something that could lead into the work on a mouse pointer.

duhrer commented 4 months ago

To summarise:

  1. Nothing but Firefox gives you control over whether your focus should count as visible.
  2. There's a Chrome preference to force all focus to be visible, but you can't read or set it from an extension.
  3. The suggested workarounds (content editable, focus but not focus-visible styling) don't seem to work.
duhrer commented 4 months ago

I was thinking of combining this with the work on "focus on scroll" (#124) and making a "pointer manager" that uses overlays to visually reinforce how you're moving around the screen.

duhrer commented 4 months ago

I'm tracking this issue against Chromium that would add support for the focusVisible parameter to Chrome.

duhrer commented 4 months ago

In addition to :focus, and :focus-visible styles, CSS outline properties are also effected. I ended up making a proof of concept that adds a box shadow around the focused element using our own focused class.

I'd like to also try having an absolutely positioned outline that changes size to match what it's enclosing, as simply adding a box-shadow ends up getting clipped and looking like parentheses for rounded buttons.

duhrer commented 4 months ago

I'm happy enough with the overlay approach vs. adding styles to the focused element. My plan now is to:

  1. Remove the other approach that added a class to the focused element.
  2. Remove those classes from focus-fix.css
  3. Convert the preference back to a boolean.
  4. Test with real sites and tweak the styles for the overlay pointer a little.
  5. Add an action to toggle the focus fix preference.

On that last point, we don't have an action to update any other preferences, but given that the built-in styles come and go, I think it makes sense here.