docs: Allow navigating search results with arrow keys (#50901)

Abinash and Gaauwe Rombouts created

Closes #50604


https://github.com/user-attachments/assets/8a85b39e-e463-4fee-bc1f-2a03fe193ce3


https://github.com/user-attachments/assets/8290bb06-1eaf-4852-9568-97654e30211e

### Results: 
Now, you can scroll the search results with the arrow keys.

### Suggestion:
While this is working, I like to propose some better UX.

When you scroll with the arrow keys, the whole search results are
scrolling along with the search bar. But, I think it would be better if
we keep the search bar fixed on top and only the results scroll. Here is
an example:


https://github.com/user-attachments/assets/af9dce73-27c6-407b-8180-2f771a85303b

If you think this will be better, please let me know, and I will update
this PR.

Thank you.

Release Notes:

- Fixed docs search results scrolling with arrow keys

---------

Co-authored-by: Gaauwe Rombouts <mail@grombouts.nl>

Change summary

docs/theme/css/chrome.css | 19 ++++++++++++-------
docs/theme/index.hbs      | 25 +++++++++++++++++++++++++
2 files changed, 37 insertions(+), 7 deletions(-)

Detailed changes

docs/theme/css/chrome.css 🔗

@@ -368,7 +368,10 @@ mark.fade-out {
 .searchbar-outer {
   margin-inline-start: auto;
   margin-inline-end: auto;
+  width: 100%;
   max-width: var(--content-max-width);
+  box-sizing: border-box;
+  padding: 16px;
 }
 
 #searchbar {
@@ -394,21 +397,21 @@ mark.fade-out {
 .searchresults-header {
   font-weight: bold;
   font-size: 1em;
-  padding-block-start: 18px;
+  padding-block-start: 0;
   padding-block-end: 0;
-  padding-inline-start: 5px;
-  padding-inline-end: 0;
   color: var(--searchresults-header-fg);
 }
 
 ul#searchresults {
   list-style: none;
   padding-inline-start: 0;
+  margin-block-end: 0;
 }
 ul#searchresults li {
   margin: 10px 0px;
   padding: 2px;
   border-radius: 2px;
+  scroll-margin-block-end: 10px;
 }
 ul#searchresults li.focus {
   background-color: var(--searchresults-li-bg);
@@ -794,8 +797,7 @@ ul#searchresults span.teaser em {
   max-height: 600px;
   display: flex;
   flex-direction: column;
-  padding: 16px;
-  overflow-y: auto;
+  overflow-y: hidden;
 
   border-radius: 8px;
   background: var(--popover-bg);
@@ -803,8 +805,11 @@ ul#searchresults span.teaser em {
   box-shadow: var(--popover-shadow);
 }
 
-.searchbar-outer {
-  width: 100%;
+.searchresults-outer {
+  flex: 1;
+  min-height: 0;
+  overflow-y: auto;
+  padding: 0px 22px 22px 22px;
 }
 
 #searchbar {

docs/theme/index.hbs 🔗

@@ -424,6 +424,31 @@
         <script src="{{ path_to_root }}elasticlunr.min.js"></script>
         <script src="{{ path_to_root }}mark.min.js"></script>
         <script src="{{ path_to_root }}searcher.js"></script>
+
+        <script>
+           (function () {
+                // Check for focused search result and bring into the view
+                const ensureVisible = () => {
+                    const focused = document.querySelector("#searchresults li.focus");
+
+                    if (focused) {
+                        focused.scrollIntoView({
+                            block: "nearest",
+                            inline: "nearest"
+                        });
+                    }
+                };
+
+                // 1. Listen for arrow key events
+                // 2. Wait for DOM to update
+                // 3. Call envsureVisible
+                document.addEventListener("keydown", function (e) {
+                    if (e.key === "ArrowDown" || e.key === "ArrowUp") {
+                        requestAnimationFrame(ensureVisible);
+                    }
+                });
+            })();
+        </script>
         {{/if}}
 
         <script src="{{ path_to_root }}clipboard.min.js"></script>