Code Monkey home page Code Monkey logo

spatial-navigation's Introduction

Spatial Navigation

npm stat npm version

Written: 2017-10-17, Updated: 2019-11-27

This repository is for supportive tools of Spatial Navigation such as polyfill, demo, and relevant documents. The spatial navigation spec has been migrated from WICG to CSS WG as an official draft according to the decision at the CSS WG meeting in TPAC 2018.

You can raise a spec issue in CSS WG, but also raise others(polyfill, demo, ideas) in WICG here.

Overview

Spatial navigation is the ability to navigate between focusable elements based on their position within a structured document. Spatial navigation is often called 'directional navigation' which enables four(top/left/bottom/right) directional navigation. Users are usually familiar with the 2-way navigation using both 'tab key' for the forward direction and 'shift+tab key' for the backward direction, but not familiar with the 4-way navigation using arrow keys.

Regarding TV remote control, game console pad, IVI jog dial with 4-way keys, and Web accessibility, the spatial navigation has been a rising important input mechanism in several industries.

Details

Why Use the Polyfill

Eventually, we expect spatial navigation to be natively supported by browsers. However, this is not yet the case.

Until then, authors who wish to experiment with providing this feature to their users can include this polyfill in their page.

It can also be used for people interested in reviewing the specification in order to test the behavior it defines in various situations.

How to Use

Installation

npm i spatial-navigation-polyfill

We recommend only using versions of the polyfill that have been published to npm, rather than cloning the repo and using the source directly. This helps ensure the version you're using is stable and thoroughly tested. See the changes in the polyfill so far.

If you do want to build from source, make sure you clone the latest tag!

Including the Polyfill in a page

Include the following code in your web page, and the polyfill will be included, enabling spatial navigation.

...
    <script src="/node_modules/spatial-navigation-polyfill/polyfill/spatial-navigation-polyfill.js"></script>
  </body>
</html>

Users can now use the keyboard's arrow keys to navigate the page.

Handling Browser Events

In the polyfill, keydown event and mouseup event are used for the spatial navigation. The event handlers of those are attached to the window object.

We recommend to use it with the polyfill as below:

  • If you want to use those event handlers for other usages besides the spatial navigation,
    • attach the event handler on the children of window object or
    • call the event handler during the capturing phase of the event.
  • If you don't want those events to work with the spatial navigation, call preventDefault().

Using the APIs

The spatial navigation specification defines several JavaScript events and APIs. Using these is not necessary to use the polyfill, and users can start using the arrow keys as soon as the polyfill is included, but they can be convenient for authors who wish to override the default behavior in some cases. See the specification for more details.

Standard APIs

Standard APIs Feature
navigate() Enables the author to trigger spatial navigation programmatically
spatialNavigationSearch() Finds the element which will gain the focus within the spatial navigation container from the currently focused element
getSpatialNavigationContainer() Gets the spatial navigation container of an element
focusableAreas() Finds focusable elements within the spatial navigation container
Navigation Events Occurs depending on the specific contextual behavior associated with spatial navigation
--spatial-navigation-contain Creates customized spatial navigation containers
--spatial-navigation-action Controls the interaction for the scrollable element
--spatial-navigation-function Selects the navigation algorithm

Experimental APIs

NOTE: The APIs below are non-standard and experimental features of the spatial navigation.

  • isContainer (element) :
    • Determines whether the element is a spatial Navigation container.
    • Returns true if the element is the spatial Navigation container, and false if not.
    • Parameter
      • element : Required.
        • Any element.
  • findCandidates (element, dir, option) :
    • Searchs all valid candidates for a certain direction.
    • Returns a list of elements.
    • Parameter
      • element : Required.
        • The currently focused element to search for candidates.
      • dir : Required.
        • The direction to find candidates.
        • It should be one of ['up', 'down', 'left', 'right'].
      • option : Optional.
        • Default value is {'mode': 'visible'}.
        • The FocusableAreasOptions to find candidates.
        • It should be {'mode': 'visible'} or { mode: 'all' }.
  • findNextTarget (element, dir, option) :
    • Indicates what is the best element to move the focus for a certain direction.
    • Returns the next target element.
      • If there is no target for the direction, it returns null.
      • If scrolling occurs, it returns the element itself.
    • Parameter
      • element : Required.
        • The currently focused element to search for candidates.
      • dir : Required.
        • The direction to find candidates.
        • It should be one of ['up', 'down', 'left', 'right'].
      • option : Optional.
        • Default value is {'mode': 'visible'}.
        • The FocusableAreasOptions to find candidates.
        • It should be {'mode': 'visible'} or { mode: 'all' }.
  • getDistanceFromTarget (element, candidateElement, dir) :
    • Calculates the distance between the currently focused element and a certain candidate element.
    • Parameter
      • element : Required.
        • The currently focused element to search for candidates.
      • candidateElement : Required.
        • The candidate element which may gain the focus.
      • dir : Required.
        • The direction to find candidates.
        • It should be one of ['up', 'down', 'left', 'right'].
  • keyMode :
    • Variable for getting or setting which key type to use for the spatial navigation.
    • value
      • It should be one of ['ARROW', 'SHIFTARROW', 'NONE'].
      • In the case of using 'NONE' value, the spatial navigation feature will be turned off.

Current Status

Browser Support for Spec

The spec hasn't been implemented in any browser yet. If any update, we will add it to here.

Browser Support for Polyfill

The Spatial Navigation Polyfill has been tested and known to work in the following browsers:

Chrome
49+
Firefox
61+
Safari
11.1+
Edge
17+
Opera
36+

Remaining Issues

The polyfill is not yet complete. It roughly matches the specification but does not yet follow it closely, and has several known issues.

See the list of open bugs in github.

FAQ

Q. I’m not sure how the spatial navigation works.

  • You can see the video that shows the spatial navigation operations in the YouTube page (link).
  • You can see the brief description for the spatial navigation in Wikipedia (link).
  • In several references below, you can get the help to understand the spatial navigation operation better.

Q. Isn’t it enough just using the relevant web frameworks?

  • Several web frameworks and extensions for the spatial navigation have been provided so far due to no support from web engines. For examples, js-spatial-navigation made by Mozilla seems one of the frameworks and its quality would be good to support the features of the spatial navigation. Spotlight library implemented by LGE is also an instance of the frameworks for the spatial navigation, even though it was deprecated now. However, the support of spatial navigation from web frameworks has some limits as follows:
    • Difficult to align native scroll behavior when moving the focus to an element out of view
    • Difficult to align native focus method for a11y support
    • Performance degradation due to the expensive cost of DOM Access
    • Inconsistency of user experience (various kinds of frameworks)
    • Impossible to control isolated frames like iframe and shadow DOM

Q. The spatial navigation seems not the general feature esp. in mobile with no physical key-based interface.

  • Honestly, the mobile(feature phone) has been a first citizen of the spatial navigation about ten years old. Before touch-based interface, the majority of interface for mobile was the key-based interface. Recently(2018-2019), KaiOS-based feature phones have been propagated mainly in several developing countries such as Africa, India, and Southeast Asia. The devices doesn't support a touch interface, so users need to use the arrow keys to select a item on all applications including a browser.

  • In the future, the input mechanism for smart devices will change to something like voice command, hand gesture, and gaze direction, but the key-based interface will never disappear, even though it'll be used as a secondary method. The key-based interface used to be evaluated as one of the most intuitive ways with a strong sense feedback of finger after pushing a key, as if it's inconvenient a touch-based keyboard without any physical keys.

Q. I would like to raise an issue or idea about spatial navigation.

  • Please put any question via the following two links:
  • Issues in CSS WG for spec issues
  • Issues in WICG WG for any other issues
  • Everything for the spatial navigation is welcome! :D

Reference

spatial-navigation's People

Contributors

anawhj avatar chrisn avatar chrisosaurus avatar frivoal avatar jeonghee27 avatar jervisfm avatar jihyerish avatar lgewtc-admin avatar malvoz avatar marcoscaceres avatar nklhtv avatar reobin avatar simenbrekken avatar yaffle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spatial-navigation's Issues

API to trigger spatial navigation

Authors may want to trigger spatial navigation via script, with something like a elm.focusUp()/ elm.focusDown() / elm.focusRight() / elm.focusLeft() syntax.

In general, this would give more flexibility to authors to explore variants of the default spatnav behavior in an Extensible Web kind of way, possibly letting us standardize common uses of this feature further down the road.

For specific examples, this could be useful in cases like:

  • allowing the author to invoke spatnav from input other than directional keys, like wasd keys, or mouse gestures, or from non-input events (arbitrary logic in JS).
  • allowing the author to override the default logic of key handling. For instance, if the browser would normally scroll down when a scrollable container is focused and the down key is pressed but the author does not want that, they could call preventDefault on the key event, and invoke focusDown() instead.

However, overall, I would support this more for its enabling potential as a low level primitive than as a solution to high level problems.

While we're at it, we should probably consider introducing the equivalent for sequential navigation (aka tab-based focusing): elm.focusNext(), elm.focusPrevious(). A little tour around stack overflow shows that there's demand for these.

Exclude the currently focused element from finding candidates / selecting the best candidate

As currently written, the currently focused element is included in the result of find candidates, and not discarded from the list later.

We should either:

  • fix find candidates so that it does not include it
  • process the result of find candidates to remove it

The later seems better, as that preserves the ability of find candidates to work as a generic algo to support focusableAreas().

Box tree? Element tree? Fragment tree? etc

We should do a thorough review of the processing model, to make sure that it consistently and correctly uses the correct tree (element tree vs box tree vs fragment tree...) and the correct ancestry relationships (parent vs containing block).

@rule for nav-loop?

It is not entirely clear to me that having different values of nav-loop on different parts of the page is useful. If there are indeed use cases that would benefit from it, the then current design (modulo issue #1 ) is fine, but if not, it introduces unnecessary complexity.

It also seems like an easy way to accidentally create designs that would frustrate users: if a DOM sub-tree has nav-loop: repeat, but there are focusable elements outside of that subtree, the users will not be able to get there. The same thing can already happen with poor usage of nav-up / nav-down / nav-right / nav-left, but doing so accidentaly seems more likely with nav-loop as a property.

This would solve the key use case, without having that downside:

@nav-loop: auto | repeat | repeat-x | repeat-y | no-repeat

Alternatively, if we end up with other spat-nav related things that belong in at-rules, we could have:

@spat-nav {
  [...]
  loop: auto | repeat | repeat-x | repeat-y | no-repeat;
}

Unless someone has use cases that call for the property, I'd suggest keeping it simple and using an at-rule.

"extensible web" approach to nav-rule

The generic spat-nav heuristic can fail, and manually coding everything with nav-up / nav-down / nav-right / nav-left can be tedious, so something along the lines of the proposed nav-rule seems very useful.

However, I think coming up with the correct design for this property will be very difficult. Instead
I think we should provide some JS primitives to let page authors and framework authors come up with their own heuristics or algorithms, and only once some clear patterns emerge, standardize that.

I think that all we'd need would be a way for the author to register a JS function that would be called back when the user attempts to navigate directionally, letting javascript figure out which element the focus should go to, and call focus() on it (and preventDefault()).

To avoid the tedium of having to set this individually on each and every element the user may need to navigate away from, this should be possible to register on any element in order to get a callback when the user tries to navigate away from any focusable element within that subtree.

Should finding candidates be recursive or not

Currently, the spec says that find candidates works from

the set of all the focusable areas that are descendants of [the container]

The polyfill, on the other hand, does not include the focusable areas that are themselves descendants of other focusable areas within the container. In other words, the spec is recursive, while the polyfill is not.

The difference can be observed in this example, by focusing the topmost blue box, and trying to go up. With the polyfill, it will no go any higher, while the spec would cause red box to be focused.

It seems that the behavior in the spec is preferable, but it there may also be a performance concern.

I lean towards considering this a bug in the polyfill, but discussion is welcome.

API and Property Bikeshedding

The property names and API names used in the spec are probably OK, as they described what they do reasonably well, but I would not go as far as calling them nice.

Better suggestions are very welcome.

  • In particular, spatnav-container is a bit questionable. Maybe we should not use the abbreviation, but if we called it spatial-navigation-container it would look like it may be a longhand of spatial-navigation, which it is not. Or maybe it is spatial-navigation that should be renamed into spatnav-something...

  • The event names (navnotarget navbeforefocus navbeforescroll) aren't too pretty either: the convention that event names should be all lower case without hyphens or underscrores does limit how nice they can be though.

  • The JS APIs are pretty descriptive and tied to the name of algorithms in the processing model, but they are quite a mouthful.: findSpatNavCandidates() selectSpatNavBestCandidate() sequentialNavSearch(). Are we happy with that?

Declarative syntax for focus looping

In the initial proposal for nav-loop which specifies an ability about the focus looping, it didn't regard the looping for each axis separately.
@frivoal pointed out considering define the focus looping for each axis.

How about adding values to nav-loop for it? Something like:

nav-loop: auto | repeat | repeat-x | repeat-y | no-repeat

Each value means:

  • repeat: The spatial focus navigation loops both horizontally and vertically.
  • repeat-x: The spatial focus navigation loops only horizontally.
  • repeat-y: The spatial focus navigation loops only vertically.
  • no-repeat: The spatial focus navigation doesn't loop.

or having separate properties can be another possibility for this:

nav-loop-x: auto | repeat | no-repeat
nav-loop-y: auto | repeat | no-repeat

[css-nav-1] How author know spatnav will work by default in specific user agent?

Hello,
Let's assume that an author makes a web page that supports spatnav.
If a running browser supports spatnav by default, the author will disable
internal implementation (maybe author implemented using javascript) for
avoiding conflict. Maybe the author wants to prevent default spatnav.

But, How to know a browser supports spatnav or not in runtime?
For example, if we can use "if (window.spatnav_enabled)", we can control
above case.

Another use case for this information is polyfill. Polyfill library can
recognize spatnav feature by reading this information.

What will this API find?

What we discussed in our meetings and hallway conversations is that we'd start with a DOM-oriented API that allows us to 'find' an element - either the next/previous one in sequential order or spatially. I'd like us to clarify what this should find, and why. Here's why I think this really matters: We learn how to use things and when that changes it is disorienting and unfamiliar, this is why ARIA defines a number of interaction patterns like, for example, a set of tabs. If you're a keyboard user (I am frequently) then you learn how tabs work. When you see tabs, you know how you expect to interact with them. It's no different for other kinds of users. If I have a set of 4 tabs and focus is on the first tab, pressing tab again does not take me to the second tab, it enters the content of the active tab. Changing the selected tab is done with keyboard directional keys.
A lot of current approaches to accessibility for things like this currently involve a concept which is referred to as "roving tab index" or "roaming tab index" (or something, we can't seem to keep that one entirely straight :))... In this example, all the tabs are tabindex="-1" - they are not in the natural sequential focus, but they are programmatically focusable.

If I am on the first tab and I programmatically used our hypothetical API to find the next one, would we expect it to find the tabindex="-1" ones that are not hidden or only tabindex="0" ones ?

Scrolling propagation

The propagation of scrolling up the ancestor chain described in the spec (for the non spatnav case) is how Chrome and Safari behave, but Firefox is different. We should get the spec and all implementations to align.

Note: this may interact with #19

How to classify the navigatable element and focusable element?

There is a difference between the focusable element and navigatable element.
An element which is navigatable but not focusable (e.g., scrollable area) can contain focusable elements.
If there is a JS API for knowing the element is navigatable or focusable, it will be useful for applying the focus navigation to the group of elements.

Here is the similar consideration in WICG discourse:
(https://discourse.wicg.io/t/extending-element-level-focus-apis/726)

nextFocusMove() instead of selectSpatNavBestCandidate() and sequentialNavSearch()?

Could we generalize element.selectSpatNavBestCandidate() and element.sequentialNavSearch() into element.nextFocusMove(direction)?

direction would be from a NavigationDirection, that includes both sequential- and spatial navigation's steps; forward, backward, up, down , left, right.

We would then lack an API for asking "Which one, out of these focuables, would spatnav go to?", but we could instead ask "Which is the focusables spatnav/tabnav would go to?". I think the latter is more useful.

Merge events into "onnavigate" or "onfocusmove"?

I'm thinking fewer events give authors a chance to write tighter JavaScript: one handler for all of the navigation-related reactions.

When authors tweak their apps' navigation, I imagine debugging being easier if they only need to break and assert things in one event handler (not 3). We will enjoy the same convenience when writing web platform tests.

Proposal: Give NavigationEvent a reason or action attribute.

From an implementor's perspective I see two advantages:

  1. We pollute GlobalEventHandlers's namespace a bit less :)
  2. Tighter web platform tests.

By the way, the event's name does not need to include before. That's already implicit from being cancelable, right?

Rename findSpatNavCandidates() to findFocusableAreas()

Currently, the suggested API could be used like this:

anyelement.findSpatNavCandidates({dir: "left", somecontainerdiv});

I'd like to flip the perspective. Now we expose this method on the element from where we want to "measure reachability" of candidates. I'd like to call this method on the node whose sub tree I want to search. I think that would result in JS that's slightly more pleasant to read.

div.findFocusableAreas() // Returns all visible focusables within the div.

div.findFocusableAreas("left") // Visible focusables within the div that are left of document.activeElement().

div.findFocusableAreas("left", startelement) // Visible focusables in the div that are left of startelement.

Question: What if startelement isn't visible?

I think that reads better than the current draft's: "If c is null, set c to the nearest ancestor of eventTarget that is a spatnav container."

Keep window.navigate() or not

In the current spec, there is navigate() which makes possible to trigger spatial navigation by specifying the value for direction, not by pressing the arrow keys.

I think the main purpose of this function is for testing.
In the near future, using arrow keys in the automatic test mechanism may be supported.
So if this function doesn't have other critical usages, we need to consider keep this in the spec or not.

Rename relatedTarget to something like nextFocus?

DOM Events already have two attributes that are named *target*; currentTarget and target.

Let's not add a third one? To me, and maybe to others who are not fluent in JavaScript, this is a bit confusing.

Readers shouldn't need to go check the spec to get an idea of what the code does.

Add a container-field to NavigationEvent

Let's add a container-attribute to NavigationEvent?

It will default to document.body unless spatnav-container imposed a restriction on the search.

When dispatching the event, the browser has this information at hand already, so why not share this possibly important piece of information to authors?

Is using the enter key the right approach?

When focusable elements are nested, the inner one is neither to the top, bottom, left, or right of the outer one (typically, though it can with overflowing layouts).

This is particularly common when there are focusable things inside a scroller, since scrollers themselves are focusable.

The spec proposes to use the enter key to "navigate inside". This is introduced in the https://wicg.github.io/spatial-navigation/#overview section, and futher detailed in file:///Users/florian/src/spatial-navigation/index.html#processing-model.

Is this the best approach? I think so, but this is worth discussing. Here are a few arguments as to why this was specified the way it is:

  • Just relying on the tab key isn't good enough, since not all spatial input devices have a tab key (remote controls, gamepads, etc)

  • legacy implementations of spatial navigation have coped decently without this feature because much legacy content was crafted specifically for TV, and used very simple layouts where the situation does not arise. Making spatnav a feature of the general web means we need to make sure it is resilient to a broader range of situations, so we need something

  • The enter key is a "natural" answer to this question, and is always available on any spatnav capable input device (otherwise it couldn't click).

  • The enter key does not have pre-existing behavior of scrollable areas, so this addition does not conflict with anything

  • A possible alternative would be that:

    1. when the focus would normally move to a scroller, we first check if it has visible focusable descendants, and automatically focus one of the descendants rather than the scroller if there are any.
    2. If a scroller is focused (maybe because no focusable descendant was visible, or maybe because we decided against implementing i), and there are visible focusable descendant the the next directional navigation would focus one of them instead of scrolling.

    This solution would also work, but it felt harder to understand for users: some scrollers can be focused, some cannot, and it may not be immediately clear why. Also, this makes it hard for a user to skip past a scroller, since its content would be directly focused. With the enter-key approach, whether to dive into an element or skip over it is the users's choice.

    That said, it is a possible consideration. Note that the root is effectively special-cased to use this logic, as the downsides mentioned above do not apply to that case, and having to press enter to get to anything at all in the page would be silly.

Does the `candidates` attribute of `SelectSpatNavBestCandidateOptions` need to be required?

It seems a way to know the best candidate just with the direction argument would be convenient (e.g. elm.selectSpatNavBestCandidate("right");),
but it may also be confusing:
Would this be expected to search only within the innermost spatnav container,
or to reproduce the full logic of running the spatial navigation steps,
and if so, does that include scrolling (probably not), or a special return value to indicate
that scrolling would have happened (maybe)?

Maybe we need a separate method for that.

Make things focusable in CSS

Other specs (most likely HTML) will probably find it convenient if we define a hook in the "Handling key presses" section to let them define what a particular element does when arrow keys are pressed and that element wants to respond (e.g. the <select> element changing which is the currently selected <option>).

EDIT: The discussion in this issue moved to a completely different, and more interesting topic. Repurposing the issue to talk about that.

Focus cannot move inside the non-focusable spatnav container

The element specified with spatial-navigation-contain CSS property isn't focusable by default.
Also, focusable elements inside the non-focusable(tabindex=-1) spatnav container cannot be reachable by moving focus with spatnav.

But current polyfill works as moving the focus inside the non-focusable spatnav container.
e.g.)

<div tabindex=-1 style="left:110px; width:250px; height:100px; --spatial-navigation-contain: contain;">
  <button class="box b3" style="top:40px; left:60px;"></button>
</div>

See: https://wicg.github.io/spatial-navigation/sample/api_spatnav_contain.html

Top level API

The current API corresponds to the "7.3 Focus Navigation Heuristics" part of the processing model. An API for the "7.2 Navigation" seems useful as well, and would enable automated testing of a much larger part of the specification.

[css-nav-1] hostile iframes

To prevent hostile third party iframes (e.g. ads) from hijacking and trapping the focus, the spatpav events (and possibly APIs, althouh I'm less sure about that) should not be available by default in cross origin iframes.

The top-level document should have a way of turning them back on for iframes it trusts.

Focus delegation

Definition: focus delegation is the behavior illustrated in this example.

As the example shows, focus delegation can be achieved using JS. We could also have level a property to turn that on automatically in a later level of the spec.

So if we want focus delegation as an option, the spec is fine as is.

However, if we would like focus delegation to be the default one that users get when authors have neither styled nor scripted the document, then it needs to be included in the processing model.

@rule for arrow-key-behavior?

Similarly to issue #4, it seems to me that arrow-key-behavior would be simpler and just as useful as an at-rule instead of a property.

iframes: focusable vs scrollable

For the current processing model to work correctly we need the thing that is focusable and the thing that is scrollable in an iframe to be the same thing. If the parenting relationship ends up wrong, the algorithm may do the wrong things. Between the host element, the document, the document element, the viewport, etc, it's non obvious.

We need to check it is defined correctly.

API for finding the next focusable element

The JS API for finding the next focusable element would be useful.

element.nextFocusableElement(optional focusNavigationOptions options)

It returns the next focusable element or the list of the focusable elements.
By using it, we can predict the focus event and prepare for it.
It can be used with the focus looping, for example, disabling the focus looping if there isn't the next focusable element.

The IDL would be:

element.nextFocusableElement(optional focusNavigationOptions options)

dictionary focusNavigationOptions {
  FocusNavigationRule rule = "nearest";
  NavigationDirection direction;   // Is this necessary? If it does, what will be the default?
}

enum FocusNavigationRule { "direction", "projection", "nearest" }
enum NavigationDirection  { "up", "down", "left", "right" }
  • If direction is omitted, the API returns the list of focusable element in 4 directions.

Remove `navbeforescroll`?

Conceptually I see spatnav as a key-hook that runs in the browser just before arrow-key scrolling. If spatnav didn't find anything to focus, it lets the standard arrow-key scrolling do its job.

navnotarget could be used to signal: "spatnav's search failed, here's your chance to do something before we hand over control to the arrow-keys".

When handling navnotarget, authors would still be able to find out, by looking at the focused element's container's overflow, if a scroll is about to happen or not.

Needs for activating spatial navigation

I think spatial-navigation CSS property in the spec is needed for

  1. Guarantees the author to provide the page with spatial navigation.

  2. Activate spatial navigation to the part of the document.

    For example, if there is a document with too many focusable elements, some people may don't want to navigate all of those with the arrow keys.
    Therefore, the author can specify spatial-navigation: active to specific elements which he/she really wants to navigate.

But do we really need this feature in the spec?
Can we let User Agent control the activation of spatial navigation?

Extract and automate test cases

The test cases in the repo cover a lot of scenario, but they're set up to be manual tests. We should refactor them and automated them as far as possible into something that could be submitted to web-platform-tests

Turn the "handling key presses" section into a pull request on UI-Events

https://wicg.github.io/spatial-navigation/#key-presses

This should be an extension of UI-EVENTS's processing model
but UI-EVENTS does not have a fully defined processing model.
It does define the events, but does not define the algorithm which
is supposed to dispatch them and respond to cancellation and so on.
Therefore, this is being written as (a rough sketch of) what that
model should be.
Once this is sufficiently detailed and tested, this should be turned into
a pull request against UI-EVENTS.

The CSS at-rule for enabling the spatial navigation

There is another possibility to enable the spatial navigation, using CSS at-rule.
Such as @navigation, it lets you define the way to move the focus in 4 directions (up/down/left/right).

@navigation can have a set of descriptors like:

  • mode: always | common | only
    • How the spatial navigation works.
    • always: The spatial focus navigation always works in preference to control UI (such as controlling the scrollbar).
    • common: The spatial focus navigation works, but controlling UI takes the higher priority than that.
    • only: The spatial focus navigation works with ignoring the UI controls.
      • This seems risky for the compatibility issue.
  • target: <id> | <class> | root
    • Where the spatial navigation is applied.
  • keys: <string> (or something means the keycode)
    • Which triggers the spatial navigation. This matches with the keycode, so the specified key will work for the input of the spatial navigation.

For example,

@navigation myNavigation{
  mode: common;
  keys: 0x26 0x28 0x25 0x27;
}
 
#sub_root {
   nav-rule: myNavigation;
}

This means that the spatial focus navigation works, but controlling UI takes the higher priority than that, and the input is arrow keys.

[css-nav-1] Consider candidates revealed after one scroll step?

When finding the candidate set, Chrome's spatnav includes focusables that would become visible after one (document*) scroll step in the navigated direction.

* We don't do this for scrollable divs but I consider that a bug. I believe spatnav should treat both document scrolling and element scrolling in the same way.

This behavior is not spec'ed. Should we?

Downsides:

  • Trickier implementation.

Upsides:

  • Better UX.
  1. One keystroke instead of two: [scroll + focus] instead of [scroll] + [focus].
  2. Focused element (and its "focus ring", if enabled) is always visible (it cannot be scrolled out).

Reordered sequential navigation

There is a recurrent complain coming form a11y people that sequential navigation (aka moving focus with the tab key) as it is today is not adequate for all use cases / all users, especially in the face of increasingly powerful tools in CSS to lay things out with relatively little connection with the document order.

This has led to suggestions that sequential navigation should follow the order property in flexbox, or that it should follow "the visual order", or to the suggestion that there should be a nav-index property, or that there should be a nav-next property, or a nav-order property, or a combination of the previous things with some mechanism to scope it to a DOM sub-tree.

There are multiple difficulties with that:

  • While the DOM tree has a natural order, a visually laid out document does not. It is in 2D, which has no inherent ordering, and on top of this color, contrast, size, movement, and more come to influence in what order things are typically perceived. This makes it far from trivial in the general case to find a linear order which could be described as "the visual order". This makes it neither easy to define an order the browser should go through, nor to find the right set of properties that authors could use to express it.

  • There seem to be multiple overlapping and conflicting requirements. Sighted mouse users who occasionally use the keyboard as a supplemental navigation aid expect different things form sighted people who primarily navigate by the keyboard, who in turn expect different things from blind or partially blind users who primarily navigate the document based on its logical structure.

Discussions in the CSS-WG and in the WICG meeting leading to the creation of this repo have generally agreed that at least some of the cases that had previously been expressed as a desire for reordered sequential navigation would probably be better server by spatial navigation. The general consensus is that a good way forward is to first focus on getting spatial navigation to work, then look for use cases that are still not adequately covered by the combination of (non-reordered) sequential navigation and spatial navigation.

To be most useful, such use cases should document:

  1. How the document is marked up
  2. How the document is laid out
  3. What class of users or what usage scenario is still not well served neither by sequential navigation nor by spatial navigation.

I have created a wiki page to document these use cases. Contributions most welcome.

Also, since this has been a long running topic, linking to (and summarizing) previous conversations would probably be useful. There's a wiki page for that too.

I would like to encourage people interested in this issue in contributing to the two wiki pages above. With that information, and once we've made enough progress on spatial navigation (See the rest of this repository for this broader topic), it will be much easier to return to this topic and see what is left to solve.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.