Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard navigation support #555

Open
weilinzung opened this issue Nov 8, 2023 · 3 comments
Open

Keyboard navigation support #555

weilinzung opened this issue Nov 8, 2023 · 3 comments

Comments

@weilinzung
Copy link

Would possible to add keyboard navigation(arrow up/down) & enter key support?

  • Arrow keys to focus item from the list
  • Enter key to select the focus of the correct item
@lincolnthree
Copy link

lincolnthree commented Nov 10, 2023

You can do this using DOM listeners and the "scrollContainer.scrollToPosition" method. Just keep track of which element is selected, then calculate the position of the next/previous one, and call the method

Personally I don't think this is something that should be "built in". But all the methods/data to make it possible are here already.

@weilinzung
Copy link
Author

weilinzung commented Nov 10, 2023

@lincolnthree that sounds workable, do you have an example? we are trying to write our custom method with CDK focusKeyManager, but the logic isn't that simple.

@lincolnthree
Copy link

lincolnthree commented Nov 10, 2023

Unfortunately not a good one. It's pretty embedded in my application, but here's the general idea:

This would track the index of the selected item (and presumably highlight it)

      {
        key: ["up"],
        label: "Editor",
        description: "Previous card in list",
        preventDefault: true,
        command: async (e) => {
          if (!InputUtil.isInputFocused() && this.controller.list.isActive()) {
            if (this.controller.list.canShiftIndex(-1)) {
              UIEvents.stopPropagation(e.event);
              this.controller.list.shiftIndex(-1); 
            }
          }
        }
      },
  {
        key: ["down"],
        label: "Editor",
        description: "Next card in list",
        preventDefault: true,
        command: async (e) => {
          if (!InputUtil.isInputFocused() && this.controller.list.isActive()) {
            if (this.controller.list.canShiftIndex(1)) {
              UIEvents.stopPropagation(e.event);
              this.controller.list.shiftIndex(1); 
            }
          }
        }
      }

Some code for figuring out the item height based on our component / wrapper for the virtual list:


    this.list = this.lists.createListManager(CARDS_OVERVIEW_LIST, {
      dimensions: () => {
        return this.grid?.scroll
          ? { childHeight: this.grid.scroll.itemHeight, itemsPerWrapGroup: this.grid.scroll.itemsPerRow }
          : { childHeight: CARD_ITEM_HEIGHT, itemsPerWrapGroup: 1 };
      },
      scrollOnIndexChanged: false,
      scrollTo: async (_x: number, y: number) => {
        this.scrollTo(y + Math.floor(this.grid.scroll._virtualWindow?.nativeElement?.offsetTop ?? 0))
      }
    });

HostListeners for keyboard binding events in Angular:

  @HostListener('document:keydown.ArrowUp', ['$event']) onPrevHandler(_event: KeyboardEvent) {
    if (this.isPrevButtonVisible && !this.isFirstStep()) {
      this.prev();
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants