Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Calculator

0

75
Views
How to make arrow key navigation on responsive card grid like google drive in React?

I have tried to achieve arrow key navigation in all 4 direction. I'm able to achieve 2 direction left and right using nextSibling and previousSibling. But not found any ways to get above and below divs. I have seen many examples for arrow key navigation on card grid layout but found not one with responsive design. When you have responsive support the number of cards in each row changes. In our case, we are having a single div with wrap to create the grid. I have seen apps like Google drive which have responsive support and arrow key navigation. Sample

7 months ago · Juan Pablo Isaza
1 answers
Answer question

0

If you are sure all your cards have the same width you can go with the below approach:
You can find the element above or below using their x and y coordinates, which you can get using the Element.getBoundingClientRect() , window.scrollX and window.scrollY methods.

moving forward with your sample,
Add a getRect() method to your layout component to get the x and y coords.

getRect = (id) => {
    const el = document.getElementById(id);
    const rect = el.getBoundingClientRect();
    const x = rect.left + window.scrollX;
    const y = rect.top + window.scrollY;
    return { el, x, y };
  };

Now add conditions for ARROW_UP and ARROW_DOWN keys to handleKeyPress() method

 else if (e.key === NAVIGATION_KEYS.ARROW_UP) {
      const { x, y } = this.getRect(selected);

      // loop back in the list and select the first element
      // that is above the current selected element and has the same x coordinate
      for (let i = list.indexOf(selected) - 1; i >= 0; i--) {
        const { el, x: tx, y: ty } = this.getRect(list[i]);

        if (x === tx && y > ty) {
          this.setState({
            selected: list[i]
          });
          el.scrollIntoView(); // scrolls the element into view, try removing it to see what it does
          break;
        }
      }
    } else if (e.key === NAVIGATION_KEYS.ARROW_DOWN) {
      const { x, y } = this.getRect(selected);

      // loop forward in the list and select the first element
      // that is below the current selected element and has the same x coordinate
      for (let i = list.indexOf(selected) + 1; i < list.length; i++) {
        const { el, x: tx, y: ty } = this.getRect(list[i]);

        if (x === tx && y < ty) {
          this.setState({
            selected: list[i]
          });
          el.scrollIntoView(); // scrolls the element into view, try removing it to see what it does
          break;
        }
      }
    }

if you want smooth scroll effect you can add the following css

html {
  scroll-behaviour: smooth;
}

I have added comments for explanation, you can ask if you don't understand something.

here's a working example forked and extended from your sample

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs