Lundalogik / lime-elements

Provides reusable web components for Lime CRM
https://lundalogik.github.io/lime-elements/versions/latest
Other
38 stars 13 forks source link

Add support for left and right keyboard navigation in limel-menu when displayed as a grid #1395

Open jgroth opened 3 years ago

jgroth commented 3 years ago

It's currently not possible to use the left and right keys on the keyboard to navigate in the menu when it is displayed as a grid. It should be possible to calculate the number of columns in the grid with something like this in order to calculate what item should be focused

getComputedStyle(element).getPropertyValue("grid-template-columns").split(" ").length;
adrianschmidt commented 3 years ago

Note that you can still access all menu items using the up and down keys, the focus just doesn't move the way you'd expect.

adrianschmidt commented 3 years ago

It seems like the handling of arrow key presses is all done by MDC, which makes this a bit harder than it might have otherwise been. But there are some functions listed here that may help: https://github.com/material-components/material-components-web/tree/v11.0.0/packages/mdc-list#mdclistfoundation

adrianschmidt commented 3 years ago

Summary of findings:

Currently, pressing the up and down arrows navigates horizontally through a grid-menu, wrapping around to the previous and next line when at the left and right edges, respectively:

image

There is a function on the MDCListFoundation called setVerticalOrientation() which can be called with false as an argument to make the list listen to left and right arrow instead of up and down arrow (docs):

image

I haven't tried using it yet, so I don't know if it also sets any other stuff, like adds css classes to the html or anything, but I'm hoping it doesn't.

If we use setVerticalOrientation(false), hopefully the menu looks and behaves in exactly the same way as it does now, except that the right arrow key navigates to the right, and the left arrow key navigates to the left, still wrapping around in exactly the way it does now.

Assuming that's the case, it's hopefully simple enough to listen to left and right arrow keypress ourselves. We can then use getSelectedIndex() and setSelectedIndex() to control which element is selected:

image

The problem then lies in figuring out what item should actually be selected. Hopefully the code Johan mentioned in the issue description can help us there:

It should be possible to calculate the number of columns in the grid with something like this in order to calculate what item should be focused

getComputedStyle(element).getPropertyValue("grid-template-columns").split(" ").length;

This code should give us the number of columns used.

The maths needed for finding the new index to select is represented in the following two functions:

function keyUp() {
    let indexToSelect = currentlySelectedIndex - numberOfColumns;
    if (indexToSelect < 0) {
        indexToSelect = indexToSelect + (items.length - (items.length % numberOfColumns)) + numberOfColumns;
        if (indexToSelect >= items.length) {
            indexToSelect = indexToSelect - numberOfColumns;
        }
    }
    return indexToSelect;
}

function keyDown() {
      let indexToSelect = currentlySelectedIndex + numberOfColumns;
      if (indexToSelect >= items.length) {
          indexToSelect = indexToSelect % numberOfColumns;
      }
    return indexToSelect;
}
adrianschmidt commented 2 weeks ago

@lattaai2 Any chance you could fix this bug for us?