Selectable list now responds to arrow key presses
This commit is contained in:
parent
d95ba45867
commit
237267ff3a
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useCallback, useRef } from "react";
|
||||||
|
|
||||||
export interface SelectableListProps<T> {
|
export interface SelectableListProps<T> {
|
||||||
items: T[];
|
items: T[];
|
||||||
@ -12,15 +12,41 @@ export const SelectableList = <T,>(
|
|||||||
): JSX.Element => {
|
): JSX.Element => {
|
||||||
const { items, selectedValue, renderLabel, onSelect } = props;
|
const { items, selectedValue, renderLabel, onSelect } = props;
|
||||||
|
|
||||||
const listClassName = "selectable-list";
|
const listRef = useRef<HTMLUListElement | null>(null);
|
||||||
|
|
||||||
|
const handleKeyDown = useCallback(
|
||||||
|
(e: React.KeyboardEvent<HTMLUListElement>) => {
|
||||||
|
if (!items.length) return;
|
||||||
|
|
||||||
|
const currentIndex = selectedValue ? items.indexOf(selectedValue) : -1;
|
||||||
|
|
||||||
|
if (e.key === "ArrowDown") {
|
||||||
|
e.preventDefault();
|
||||||
|
const nextIndex =
|
||||||
|
currentIndex < items.length - 1 ? currentIndex + 1 : 0;
|
||||||
|
onSelect(items[nextIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === "ArrowUp") {
|
||||||
|
e.preventDefault();
|
||||||
|
const prevIndex =
|
||||||
|
currentIndex > 0 ? currentIndex - 1 : items.length - 1;
|
||||||
|
onSelect(items[prevIndex]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[items, selectedValue, onSelect],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className={listClassName}>
|
<ul
|
||||||
|
ref={listRef}
|
||||||
|
className="selectable-list"
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
>
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
const isSelected = selectedValue === item;
|
const isSelected = selectedValue === item;
|
||||||
const className = isSelected
|
const className = isSelected ? "selected" : "";
|
||||||
? ["selected"].filter(Boolean).join(" ")
|
|
||||||
: "";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={index} onClick={() => onSelect(item)} className={className}>
|
<li key={index} onClick={() => onSelect(item)} className={className}>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user