]> BookStack Code Mirror - website/commitdiff
Added arrow key support to search dialog
authorDan Brown <redacted>
Wed, 9 Jul 2025 21:13:30 +0000 (22:13 +0100)
committerDan Brown <redacted>
Wed, 9 Jul 2025 21:13:30 +0000 (22:13 +0100)
themes/bookstack/layouts/partials/header.html
themes/bookstack/static/js/script.js

index c655ec173e9b2a19c345f4694cc43d0c8c85322d..031b9c29d430ed043059bfdf80e8923074978898 100644 (file)
@@ -93,7 +93,7 @@
       </div>
       <div class="header-search-section">
         <form id="site-search-form">
-          <input id="site-search-input" type="search" placeholder="Search site" value="">
+          <input id="site-search-input" autocomplete="off" type="search" placeholder="Search site" value="">
           <dialog>
           </dialog>
         </form>
index 385a74a9fab1abe3b76416f77753a50146f35db1..6b7e5a7a15e812011e02547221a50ef9d66c02f0 100644 (file)
@@ -129,33 +129,59 @@ function showSearchDialog() {
   }
   searchDialog.show();
   searchInput.focus();
-  
+
   const clickListener = e => {
-    if(!e.target.closest('dialog')) {
+    if (!e.target.closest('dialog')) {
       closeListener();
     }
   };
 
   const escListener = e => {
     if (e.key === 'Escape') {
-        closeListener();
+      closeListener();
     }
   };
 
+  const arrowListener = e => {
+    if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') {
+      return;
+    }
+    e.preventDefault();
+
+    const links = Array.from(searchDialog.querySelectorAll('a'));
+    const focusables = [searchInput, ...links];
+    if (focusables.length < 2) { // Only search input
+      return;
+    }
+
+    const active = document.activeElement;
+    let currentIndex = focusables.indexOf(active);
+
+    if (e.key === 'ArrowDown') {
+      currentIndex = (currentIndex + 1) % focusables.length;
+    } else { // ArrowUp
+      currentIndex = (currentIndex - 1 + focusables.length) % focusables.length;
+    }
+
+    focusables[currentIndex].focus();
+  };
+
   const mouseLeaveListener = e => {
     closeListener();
-  }
+  };
 
   const closeListener = () => {
     searchDialog.close();
     document.removeEventListener('click', clickListener);
     document.removeEventListener('keydown', escListener);
     searchForm.removeEventListener('mouseleave', mouseLeaveListener);
+    searchForm.removeEventListener('keydown', arrowListener);
   };
 
   document.addEventListener('click', clickListener);
   document.addEventListener('keydown', escListener);
   searchForm.addEventListener('mouseleave', mouseLeaveListener);
+  searchForm.addEventListener('keydown', arrowListener);
 }
 
 function showSearchLoading() {