fluid-lab / gamepad-navigator

GSoC 2020 project
Other
6 stars 10 forks source link

"Jump to Content" links do not shift focus properly. #99

Closed duhrer closed 5 months ago

duhrer commented 8 months ago

Many sites provide a "jump to content" link that is the first focusable element when navigating using tabs (or the gamepad navigator). For an example, just look at any page in Wikipedia.

When you "click" the "jump to content" link with the gamepad navigator, the window scrolls past the header to the content. However, if you then use the next/previous element navigation controls (left and right bumpers by default), the focus immediately returns to the "jump to content" link.

If you hit tab or shift+tab after clicking "jump to content", the focus moves to the next/previous element relative to the target of the internal link.

duhrer commented 8 months ago

I suspect it's down to this section of input-mapper-content-utils.js:

                var activeElement = document.activeElement;
                if (activeElement.nodeName === "BODY" || !activeElement) {
                    that.tabbableElements[0].focus();
                }
                else {
                    var activeElementIndex = that.tabbableElements.indexOf(activeElement);

                    /**
                     * If the currently focused element is not found in the list, refer to
                     * the stored value of the index.
                     */
                    if (activeElementIndex === -1) {
                        activeElementIndex = that.currentTabIndex;
                    }

If the target is "tabbable", then its position in the list of "tabbables" can be determined and navigation can happen. If the target is not a "tabbable", then the current tab index is used.

To solve this, we'd need to instead calculate the nearest "tababble" from the active element, which ally.query.tabbable does support, via the context parameter. The first tabbable after the context is the target element for moving forward (i.e. when direction is positive), we can figure out its "index" from our existing list of tabbables. If direction is negative, we'd have to find the index of the next element and go back one.

However, our strategy is based on the element that has focus, and if the link target is not itself focusable, the active element remains set to the body. Since the scrolling changes, we could detect the first onscreen element and look for the next tabbable from there.

This adds a little complexity, but would also improve the navigation when scrolling. Currently, if you scroll down screen and then use the "tab navigation" controls, you jump back to wherever last had focus (or the body if nothing had focus). This is the same behaviour you get when scrolling with a mouse wheel or keyboard.

Maybe add this kind of onscreen element detection and make it a preference?

duhrer commented 5 months ago

I ended up addressing this by temporarily making whatever a page anchor points to focusable if necessary, and focusing on that element. If the target was not previously focusable, it will stop being focusable when it is next "blurred".