Skip to content

Commit

Permalink
maintain focus on search input
Browse files Browse the repository at this point in the history
  • Loading branch information
selfcontained committed Oct 11, 2023
1 parent ff54f36 commit 095aaad
Showing 1 changed file with 45 additions and 27 deletions.
72 changes: 45 additions & 27 deletions components/dashboard/src/components/DropDown2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,11 @@ export const DropDown2: FunctionComponent<DropDown2Props> = ({

const handleInputChange = useCallback((e) => updateSearch(e.target.value), [updateSearch]);

const setFocussedElement = useCallback(
const setActiveElement = useCallback(
(element: string) => {
setSelectedElementTemp(element);
const el = document.getElementById(element);
el?.scrollIntoView({ block: "nearest" });
el?.focus();
},
[setSelectedElementTemp],
);
Expand All @@ -96,36 +95,48 @@ export const DropDown2: FunctionComponent<DropDown2Props> = ({
[updateSearch],
);

const focusNextElement = useCallback(() => {
let idx = filteredOptions.findIndex((e) => e.id === selectedElementTemp);
while (idx++ < filteredOptions.length - 1) {
const candidate = filteredOptions[idx];
if (candidate.isSelectable) {
setActiveElement(candidate.id);
return;
}
}
}, [filteredOptions, selectedElementTemp, setActiveElement]);

const focusPreviousElement = useCallback(() => {
let idx = filteredOptions.findIndex((e) => e.id === selectedElementTemp);

while (idx-- > 0) {
const candidate = filteredOptions[idx];
if (candidate.isSelectable) {
setActiveElement(candidate.id);
return;
}
}
}, [filteredOptions, selectedElementTemp, setActiveElement]);

const onKeyDown = useCallback(
(e: React.KeyboardEvent) => {
if (e.key === "ArrowDown") {
e.preventDefault();
let idx = filteredOptions.findIndex((e) => e.id === selectedElementTemp);
while (idx++ < filteredOptions.length - 1) {
const candidate = filteredOptions[idx];
if (candidate.isSelectable) {
setFocussedElement(candidate.id);
return;
}
}
focusNextElement();
return;
}
if (e.key === "ArrowUp") {
e.preventDefault();
let idx = filteredOptions.findIndex((e) => e.id === selectedElementTemp);

// Shfit focus back to search input if we're at the top
if (idx === 0) {
inputEl.current?.focus();
return;
}

while (idx-- > 0) {
const candidate = filteredOptions[idx];
if (candidate.isSelectable) {
setFocussedElement(candidate.id);
return;
}
focusPreviousElement();
return;
}
if (e.key === "Tab") {
e.preventDefault();
if (e.shiftKey) {
focusPreviousElement();
e.stopPropagation();
} else {
focusNextElement();
}
return;
}
Expand All @@ -145,7 +156,15 @@ export const DropDown2: FunctionComponent<DropDown2Props> = ({
e.preventDefault();
}
},
[filteredOptions, handleOpenChange, inputEl, onSelected, search, selectedElementTemp, setFocussedElement],
[
filteredOptions,
focusNextElement,
focusPreviousElement,
handleOpenChange,
onSelected,
search,
selectedElementTemp,
],
);

const showInputLoadingIndicator = filteredOptions.length > 0 && loading;
Expand Down Expand Up @@ -215,7 +234,7 @@ export const DropDown2: FunctionComponent<DropDown2Props> = ({
element={element}
isActive={element.id === selectedElementTemp}
onSelected={onSelected}
onFocused={setFocussedElement}
onFocused={setActiveElement}
/>
);
})
Expand Down Expand Up @@ -296,7 +315,6 @@ export const Dropdown2Element: FC<Dropdown2ElementProps> = ({ element, isActive,
return (
<li
id={element.id}
tabIndex={0}
className={"h-min rounded-lg flex items-center px-2 py-1.5 " + selectionClasses}
onMouseDown={() => {
if (element.isSelectable) {
Expand Down

0 comments on commit 095aaad

Please sign in to comment.