npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue3-spatialnavigation

v0.0.9

Published

Simple spatial navigation for vue3

Downloads

32

Readme

Version Downloads

Introduction

This is a Vue3 Javascript-only adaptation of the Vue2 Spatial Navigation directive from https://github.com/twcapps/vue-spatialnavigation

Installation

npm install vue3-spatialnavigation --save

Spatial navigation

Spatial navigation is keyboard navigation of a html page most often used on devices where mouse navigation is not available or not preferred. An important rule is that only 1 element can have the active 'focus' state at the same time.

When a user navigates the page with the left, right, up, down keybaord keys a decision should be made which element to focus next. This directive will improve the Vue native keyboard binding to provide a flexible spatial navigation implementation.

Inspiration for this plugin is taken from the CSS3 draft keyboard navigation, a limitation is that CSS3 can only point the focus position based on (DOM) element id pointers, while this directive supports both element id pointers and custom (component) method binding.

Typical usage

To make an element 'focusable' just add the focus directive

import { createApp } from 'vue'
import VueSpatialNavigation from "vue3-spatialnavigation";
const app = createApp();
app.use(VueSpatialNavigation);
<Component id="button1" v-spat></Component>
<Component id="button2" v-spat></Component>

CSS3 Element binding

Use data properties with a domId string reference to determine the focus action during navigation (this behaves similar to the CSS3 draft)

<Component id="button1" v-spat data-down="button2"></Component>
<Component id="button2" v-spat data-up="button1"></Component>

JS Component binding

Use vue bind directive with a component function reference to determine the focus action during navigation.

<Component id="button1" v-spat @down="componentFunctionDown"></Component>
<Component id="button2" v-spat @up="componentFunctionUp" ></Component>
import { createApp } from 'vue'
import VueSpatialNavigation from "vue3-spatialnavigation";
const app = createApp();
app.use(VueSpatialNavigation, {
  methods: {
    componentFunctionDown: () => {
      let el = navigationService.getFocusElementById("button2");
      if (el) el.focus()
    },
    componentFunctionUp: () =>  {
      let el = navigationService.getFocusElementById("button1");
      if (el) el.focus()
    }
  }
})

Automatic focus handling

Use the special constant value 'AUTOFOCUS' to let the directive try to find the next focusable sibbling automatically. This only works if the next/prev focusable element is a sibling within the parent container!

<Component id="button1" v-spat data-down="AUTOFOCUS"></Component>
<Component id="button2" v-spat data-up="AUTOFOCUS"></Component>

Determine the first or default focus element

In case the page is just rendered and or focus is reset the directive should know which element to restore focus to. The directive will keep a reference to the last focussed element, but if that is not available it will restore focus to the 'default' focus element on the page.

<Component id="button1" v-spat data-default data-down="button2"></Component>
<Component id="button2" v-spat data-up="button1"></Component>

Enter action

When a user actions an 'enter' keypress it will automatically be converted into a click action on the element that has active focus. So you can use the regular vue @click bindings. Note that by default vue only supports @click on html elements and you have to normally use @click.native on a component, this directive will automatically capture the native event though and convert it into a vue event so you can use @click for both native keyboard and mouse clicks.

<Component id="button1" v-spat @down="componentFunctionDown"></Component>
<Component id="button2" v-spat @up="componentFunctionUp" @click="button2clicked"></Component>
import { createApp } from 'vue'
import VueSpatialNavigation from "vue3-spatialnavigation";
const app = createApp();
app.use(VueSpatialNavigation, {
  methods: {
    componentFunctionDown: () => {
      let el = navigationService.getFocusElementById("button2");
      if (el) el.focus()
    },
    componentFunctionUp: () =>  {
      let el = navigationService.getFocusElementById("button1");
      if (el) el.focus()
    },
    button2clicked: () => {
      console.log("button2clicked");
    }
  }
})

Configuration

The application uses a default keybinding for the d-pad and enter keys, during the directive initialisation this can optionally be overriden with the options object:

import { createApp } from 'vue'
import VueSpatialNavigation from "vue3-spatialnavigation";
const app = createApp();
app.use(VueSpatialNavigation, {
  keyCodes: {
    "up": 38,
    "down": 40,
    "left": 37,
    "right": 39,
    "enter": 13
  }
})

It is also possible to override the NavigationService class to create a fully custom key binding.

import { createApp } from 'vue'
import VueSpatialNavigation from "vue3-spatialnavigation";
import { NavigationService } from "vue3-spatialnavigation/navigation";
// custom navigation service 
class CustomNavigationService extends NavigationService {

}
const app = createApp();
app.use(VueSpatialNavigation, {
  navigationService: CustomNavigationService
})

Styling

The directive will automatically assigned and remove the class "focus" on the html element to distingish an element in focus vs an element not in focus. The css "focus" class handling is fully handled by the directive and should not be changed/set manually.

<style>
.focus { background-color: yellow;}
</style>
<Component id="button1" v-spat data-default data-down="AUTOFOCUS"></Component>
<Component id="button2" v-spat data-up="AUTOFOCUS"></Component>

NavigationService

In addition to the directive this plugin also exposes a NavigationService object that allows control of the focusable elements from JS code. The navigation service keeps track of all focusable elements on the page and can be used to query focusable elements/

It provides the below properties:

blockAllSpatialNavigation   // enabled / disable a navigation block (e.g. during loading)

It provides the below methods:

NavigationService.getFocusElementInFocus()         // get FocusElement currently in focus
NavigationService.getFocusElementById(id)          // get FocusElement by DOM id
NavigationService.getFocusElementIsDefault()       // get FocusElement by default property
NavigationService.blurAllFocusElements()           // blur all FocusElements

FocusElement

FocusElement is a class initialised for each dom element where the directive is applied, you can aquire the FocusElement by quering the NavigationService.

It provides the below properties:

  FocusElement.id        // dom id reference
  FocusElement.isFocus   // is element currently focussed
  FocusElement.isDefault // is element a default focusable element

And the below properties:

  FocusElement.focus()  // manually focus the current element
  FocusElement.blur()   // manually blur the current element
  FocusElement.left()   // manually trigger left action the current element
  FocusElement.right()  // manually trigger right action the current element
  FocusElement.up()     // manually trigger up action the current element
  FocusElement.down()   // manually trigger down action the current element
  FocusElement.enter()  // manually trigger enter action the current element