简体   繁体   中英

How to increase the tabindex in React ul-li search result?

I used ul li to implement search result:

<ul className="search-result">
  <li tabindex="1">title here...</li>
  <li tabindex="2">title here...</li>
  <li tabindex="3">title here...</li>
.
.
.
</ul>

and this is the style for each item:

.search-result{
 li:active, li:focuse {
  font-weight: bold;
  background: #f0f0f0;
 }
}

but I'm trying to add a feature which client navigate between result items by using key-down or key-up buttons on the keyboard. but how can I access to current active tabindex in document to increase or decrease that by JavaScript and not tab button?

Do you want to tab to each <li> (search result) and use the up/down arrow keys to navigate through the list?

You have to be careful when using positive values for tabindex . It should rarely be used because it changes the default browser focus order which most users are used to. The default focus order is DOM order. In your case, if you want the user to tab to each <li> in order, you don't need a positive value for tabindex because your <li> elements are already in the order you want them tabbed to. Just set them all to 0. A value of 0 means that the DOM element should be inserted into the tab order in the normal DOM order.

<ul className="search-result">
  <li tabindex="0">title here...</li>
  <li tabindex="0">title here...</li>
  <li tabindex="0">title here...</li>
.
.
.
</ul>

Now, having said that, elements should only have tabindex="0" if they are interactive elements. An <li> is not normally an interactive element so it'll be confusing to tab to it. What can the user do once they tab to the <li> ? Can they press enter or space to select it? If the user can't interact with that element, then it should not be a tab stop.

Typically, the <li> contains things that are interactive, such as links, buttons, checkboxes, etc. Those elements are already tab stops by default and don't need a tabindex .

As far as using up/down arrow keys for navigation, again, you should only be able to arrow to elements that are interactive. I normally have an onkeydown handler on the <ul> and it listens for the arrow keys and adjusts the tabindex for each item. But I only do this when I want my entire list to be one tab stop and the user must arrow up/down to go between each list item. In your case, it sounds like you want both behaviors which is why I asked the question at the beginning of my answer.

If the list is treated as one tab stop, then all <li> elements will have a tabindex="-1" except for the <li> that has focus. It will have tabindex="0" . That way the user can tab to the list as a whole and the focus will go to the list item that last had focus. The user can then up/down through the list.

When the user presses up/down, all you have to do is change tabindex from 0 to -1 for the currently focused list item and change tabindex from -1 to 0 for the list item you're moving focus to, and then call focus() on the newly focused element.

You need store current tab index in state and update it in keydown eventListener

import "./styles.css";
import { useState, useEffect } from "react";
import users from "./data";

export default function App() {
  const [searchValue, setSearchValue] = useState("");
  const [currentTab, setCurrentTab] = useState(0);
  const searchResults = users.filter(
    (user) => searchValue.trim() && user.includes(searchValue.trim())
  );
  useEffect(() => {
    const handleKeyDown = (e) => {
      const keyCode = e.keyCode;
      if (keyCode == 38 && searchResults.length - 1 > currentTab)
        setCurrentTab(currentTab + 1);
      if (keyCode == 40 && currentTab >= 1) setCurrentTab(currentTab - 1);
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [searchResults, currentTab]);
  return (
    <div>
      <input
        type="text"
        value={searchValue}
        onChange={(e) => {
          setSearchValue(e.target.value);
          setCurrentTab(0);
        }}
      />
      <ul className="search-result">
        {searchResults.map((result, i) => (
          <li className={currentTab === i ? "active" : ""}>{result}</li>
        ))}
      </ul>
    </div>
  );
}

I created a sandbox , you can check it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM