From bac386057a990200112b136674933b0220ac0ea8 Mon Sep 17 00:00:00 2001
From: ivarlovlie <git@ivarlovlie.no>
Date: Fri, 3 Jun 2022 00:27:12 +0200
Subject: refactor: Dont loose focus on search input when navigating results

---
 apps/web-shared/src/components/dropdown.svelte | 50 +++++++++++++++-----------
 1 file changed, 30 insertions(+), 20 deletions(-)

(limited to 'apps/web-shared/src/components/dropdown.svelte')

diff --git a/apps/web-shared/src/components/dropdown.svelte b/apps/web-shared/src/components/dropdown.svelte
index b5068a7..2cddce9 100644
--- a/apps/web-shared/src/components/dropdown.svelte
+++ b/apps/web-shared/src/components/dropdown.svelte
@@ -25,7 +25,6 @@
 
     const INTERNAL_ID = "__dropdown-" + random_string(5);
 
-    let entriesUlNode;
     let searchInputNode;
     let searchResults = [];
     let searchValue = "";
@@ -34,7 +33,7 @@
     let lastKeydownCode = "";
     let mouseIsOverDropdown = false;
     let mouseIsOverComponent = false;
-    
+
     $: hasSelection = entries.some((c) => c.selected === true);
     $: if (searchValue.trim()) {
         showCreationHint = createable && entries.every((c) => search.normalise_value(c.name) !== search.normalise_value(searchValue));
@@ -74,6 +73,7 @@
             if (selected && !multiple) {
                 searchValue = selected.name;
             }
+            document.querySelector("#" + INTERNAL_ID + " ul li.focus")?.classList.remove("focus");
             showDropdown = false;
         }
     };
@@ -191,7 +191,7 @@
             const spacePressed = event.code === "Space";
             const arrowDownPressed = event.code === "ArrowDown";
             const searchInputHasFocus = element_has_focus(searchInputNode);
-            const focusedEntry = entriesUlNode?.querySelector("li:focus");
+            const focusedEntry = document.querySelector("#" + INTERNAL_ID + " ul    .focus");
 
             if (showDropdown && (enterPressed || arrowDownPressed)) {
                 event.preventDefault();
@@ -204,28 +204,39 @@
                 }
                 return;
             }
+            if (searchInputHasFocus && enterPressed && showCreationHint) {
+                methods.create_entry(searchValue.trim());
+                return;
+            }
 
-            if (searchInputHasFocus) {
-                if (enterPressed && showCreationHint) {
-                    methods.create_entry(searchValue.trim());
-                    return;
-                }
-
-                if (arrowDownPressed) {
-                    const firstEntry = entriesUlNode.querySelector("li:first-of-type");
-                    if (firstEntry) {
-                        firstEntry.focus();
-                    }
+            if (searchInputHasFocus && !focusedEntry && arrowDownPressed) {
+                const firstEntry = document.querySelector("#" + INTERNAL_ID + " ul li:first-of-type");
+                if (firstEntry) {
+                    firstEntry.classList.add("focus");
                     return;
                 }
             }
 
             if (focusedEntry && (arrowUpPressed || arrowDownPressed)) {
-                if (arrowDownPressed && focusedEntry.nextElementSibling) {
-                    focusedEntry.nextElementSibling.focus();
-                } else if (arrowUpPressed && focusedEntry.previousElementSibling) {
-                    focusedEntry.previousElementSibling.focus();
+                if (arrowDownPressed) {
+                    if (focusedEntry.nextElementSibling) {
+                        focusedEntry.nextElementSibling.classList.add("focus");
+                        focusedEntry.nextElementSibling.scrollIntoView();
+                    } else {
+                        document.querySelector("#" + INTERNAL_ID + " ul li:first-of-type").classList.add("focus");
+                        document.querySelector("#" + INTERNAL_ID + " ul li:first-of-type").scrollIntoView();
+
+                    }
+                } else if (arrowUpPressed) {
+                    if (focusedEntry.previousElementSibling) {
+                        focusedEntry.previousElementSibling.classList.add("focus");
+                        focusedEntry.previousElementSibling.scrollIntoView();
+                    } else {
+                        document.querySelector("#" + INTERNAL_ID + " ul li:last-of-type").classList.add("focus");
+                        document.querySelector("#" + INTERNAL_ID + " ul li:last-of-type").scrollIntoView();
+                    }
                 }
+                focusedEntry.classList.remove("focus");
                 return;
             }
 
@@ -330,8 +341,7 @@
 
     <!-- dropdown -->
     <div class="autocomplete__results select-auto__results">
-        <ul bind:this={entriesUlNode}
-            on:keydown={(event) => event.code.startsWith("Arrow") && event.preventDefault()}
+        <ul on:keydown={(event) => event.code.startsWith("Arrow") && event.preventDefault()}
             tabindex="-1"
             class="autocomplete__list">
             {#if searchResults.length > 0}
-- 
cgit v1.3

