From bfc584d652bf908ff62d2e559adecbbcfd6d801d Mon Sep 17 00:00:00 2001 From: Anay Garodia Date: Wed, 8 Jul 2026 15:17:26 -0700 Subject: [PATCH 1/7] docs: page through the guide with Left/Right arrow keys Add a small keyboard-nav script (wired via zensical extra_javascript) that maps ArrowLeft/ArrowRight to the previous/next footer links, matching the common paged-site pattern. A single document-level listener keeps working across instant navigation, looks up the current page's footer links on each key press, and ignores key presses while a modifier is held or a form field (e.g. the search box) is focused. Fixes #2788 --- docs/content/javascripts/keyboard-nav.js | 52 ++++++++++++++++++++++++ zensical.toml | 3 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 docs/content/javascripts/keyboard-nav.js diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js new file mode 100644 index 0000000000..aa508bd728 --- /dev/null +++ b/docs/content/javascripts/keyboard-nav.js @@ -0,0 +1,52 @@ +// Keyboard navigation for the documentation guide. +// +// Left/Right arrow keys page through the guide, following the same +// previous/next links that are shown in the page footer. This mirrors the +// common "prev/next" behavior of left/right paged sites. +// +// See https://github.com/maplibre/martin/issues/2788 +(function () { + "use strict"; + + // Don't hijack the arrow keys while the user is typing (e.g. in the search + // box) or interacting with a form control. + function isTypingTarget(el) { + if (!el) { + return false; + } + if (el.isContentEditable) { + return true; + } + var tag = el.tagName; + return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT"; + } + + // A single document-level listener keeps working across "instant" navigation, + // where the page body is swapped without a full reload. The footer links are + // looked up on each key press so they always point at the current page. + document.addEventListener("keydown", function (event) { + // Leave modifier combinations alone (e.g. browser back/forward shortcuts). + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } + if (isTypingTarget(document.activeElement)) { + return; + } + + var selector; + if (event.key === "ArrowLeft") { + selector = "a.md-footer__link--prev[href]"; + } else if (event.key === "ArrowRight") { + selector = "a.md-footer__link--next[href]"; + } else { + return; + } + + var link = document.querySelector(selector); + if (link && link.getAttribute("href")) { + event.preventDefault(); + // Use click() so "instant" navigation (if enabled) can intercept it. + link.click(); + } + }); +})(); diff --git a/zensical.toml b/zensical.toml index c5a56f21fe..ee34bd309b 100644 --- a/zensical.toml +++ b/zensical.toml @@ -127,7 +127,8 @@ nav = [ # The path provided should be relative to the "docs_dir". # # Read more: https://zensical.org/docs/customization/#additional-javascript -#extra_javascript = ["javascripts/extra.js"] +# Enables Left/Right arrow keys to page through the guide (issue #2788). +extra_javascript = ["javascripts/keyboard-nav.js"] # ---------------------------------------------------------------------------- # Section for configuring theme options From a20a851a59051903c8d169b47f3ca63c505ab0d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:21:01 +0000 Subject: [PATCH 2/7] chore(fmt): apply pre-commit formatting fixes --- docs/content/javascripts/keyboard-nav.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js index aa508bd728..f9dc48cf17 100644 --- a/docs/content/javascripts/keyboard-nav.js +++ b/docs/content/javascripts/keyboard-nav.js @@ -5,9 +5,7 @@ // common "prev/next" behavior of left/right paged sites. // // See https://github.com/maplibre/martin/issues/2788 -(function () { - "use strict"; - +(() => { // Don't hijack the arrow keys while the user is typing (e.g. in the search // box) or interacting with a form control. function isTypingTarget(el) { @@ -18,13 +16,13 @@ return true; } var tag = el.tagName; - return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT"; + return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT'; } // A single document-level listener keeps working across "instant" navigation, // where the page body is swapped without a full reload. The footer links are // looked up on each key press so they always point at the current page. - document.addEventListener("keydown", function (event) { + document.addEventListener('keydown', (event) => { // Leave modifier combinations alone (e.g. browser back/forward shortcuts). if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; @@ -34,16 +32,16 @@ } var selector; - if (event.key === "ArrowLeft") { - selector = "a.md-footer__link--prev[href]"; - } else if (event.key === "ArrowRight") { - selector = "a.md-footer__link--next[href]"; + if (event.key === 'ArrowLeft') { + selector = 'a.md-footer__link--prev[href]'; + } else if (event.key === 'ArrowRight') { + selector = 'a.md-footer__link--next[href]'; } else { return; } var link = document.querySelector(selector); - if (link && link.getAttribute("href")) { + if (link && link.getAttribute('href')) { event.preventDefault(); // Use click() so "instant" navigation (if enabled) can intercept it. link.click(); From 1fdb360e95641baf488ebbeb33a47143d3a22cc5 Mon Sep 17 00:00:00 2001 From: Anay Garodia Date: Wed, 8 Jul 2026 16:34:36 -0700 Subject: [PATCH 3/7] docs: de-vibe comments --- docs/content/javascripts/keyboard-nav.js | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js index f9dc48cf17..83d9cbac19 100644 --- a/docs/content/javascripts/keyboard-nav.js +++ b/docs/content/javascripts/keyboard-nav.js @@ -1,13 +1,7 @@ -// Keyboard navigation for the documentation guide. -// -// Left/Right arrow keys page through the guide, following the same -// previous/next links that are shown in the page footer. This mirrors the -// common "prev/next" behavior of left/right paged sites. -// -// See https://github.com/maplibre/martin/issues/2788 +// left/right arrow keys page through the docs guide, following the prev/next +// links shown in the page footer (#2788). (() => { - // Don't hijack the arrow keys while the user is typing (e.g. in the search - // box) or interacting with a form control. + // don't hijack arrows while typing in the search box or a form control function isTypingTarget(el) { if (!el) { return false; @@ -19,11 +13,10 @@ return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT'; } - // A single document-level listener keeps working across "instant" navigation, - // where the page body is swapped without a full reload. The footer links are - // looked up on each key press so they always point at the current page. + // one document-level listener survives "instant" navigation (body swapped, no + // full reload); re-query the footer links each keypress so they track the current page. document.addEventListener('keydown', (event) => { - // Leave modifier combinations alone (e.g. browser back/forward shortcuts). + // leave modifier combos alone — e.g. browser back/forward shortcuts if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } @@ -43,7 +36,7 @@ var link = document.querySelector(selector); if (link && link.getAttribute('href')) { event.preventDefault(); - // Use click() so "instant" navigation (if enabled) can intercept it. + // click() so "instant" navigation can intercept it link.click(); } }); From deaab7c213de8180daa06fb98e4273e7e7ff6bc0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 23:34:58 +0000 Subject: [PATCH 4/7] chore(fmt): apply pre-commit formatting fixes --- docs/content/javascripts/keyboard-nav.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js index 83d9cbac19..60ff026cf6 100644 --- a/docs/content/javascripts/keyboard-nav.js +++ b/docs/content/javascripts/keyboard-nav.js @@ -16,7 +16,7 @@ // one document-level listener survives "instant" navigation (body swapped, no // full reload); re-query the footer links each keypress so they track the current page. document.addEventListener('keydown', (event) => { - // leave modifier combos alone — e.g. browser back/forward shortcuts + // leave modifier combos alone - e.g. browser back/forward shortcuts if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } From d5efbdb4f59072ccbf5def664690cd647b277005 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Thu, 9 Jul 2026 11:04:45 +0200 Subject: [PATCH 5/7] Apply suggestion from @CommanderStorm --- zensical.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/zensical.toml b/zensical.toml index ee34bd309b..e87945ce9c 100644 --- a/zensical.toml +++ b/zensical.toml @@ -127,7 +127,6 @@ nav = [ # The path provided should be relative to the "docs_dir". # # Read more: https://zensical.org/docs/customization/#additional-javascript -# Enables Left/Right arrow keys to page through the guide (issue #2788). extra_javascript = ["javascripts/keyboard-nav.js"] # ---------------------------------------------------------------------------- From 1ecef38ec2b2fae77e1e4d8ed2ab08624dc9bbb6 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Fri, 10 Jul 2026 02:16:35 +0200 Subject: [PATCH 6/7] simplify some comments --- docs/content/javascripts/keyboard-nav.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js index 60ff026cf6..e2ea294756 100644 --- a/docs/content/javascripts/keyboard-nav.js +++ b/docs/content/javascripts/keyboard-nav.js @@ -1,5 +1,4 @@ -// left/right arrow keys page through the docs guide, following the prev/next -// links shown in the page footer (#2788). +// left/right arrow keys page through the docs guide (() => { // don't hijack arrows while typing in the search box or a form control function isTypingTarget(el) { @@ -13,8 +12,8 @@ return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT'; } - // one document-level listener survives "instant" navigation (body swapped, no - // full reload); re-query the footer links each keypress so they track the current page. + // one document-level listener survives "instant" navigation (body swapped, no full reload) + // re-query the footer links each keypress so they track the current page document.addEventListener('keydown', (event) => { // leave modifier combos alone - e.g. browser back/forward shortcuts if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { From 426d6c9b88233b2ba11624583019cd08eb6d625d Mon Sep 17 00:00:00 2001 From: Anay Garodia Date: Thu, 9 Jul 2026 17:46:50 -0700 Subject: [PATCH 7/7] fix(docs): don't hijack arrow keys while search is open The keydown handler only bailed when focus was in the search input, but arrowing through the search results moves focus onto a result link, so Left/Right got hijacked and navigated the page out from under the open search. Bail whenever the search overlay is open, keyed on the theme's own `#__search` toggle checkbox, so arrow-key handling stays with search. --- docs/content/javascripts/keyboard-nav.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/content/javascripts/keyboard-nav.js b/docs/content/javascripts/keyboard-nav.js index e2ea294756..dad46ceb76 100644 --- a/docs/content/javascripts/keyboard-nav.js +++ b/docs/content/javascripts/keyboard-nav.js @@ -19,6 +19,14 @@ if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } + // don't hijack arrows while the search overlay is open: the user is either + // typing a query or arrowing through the results, which moves focus onto the + // result links (so an activeElement check alone doesn't cover it). `#__search` + // is the theme's search toggle checkbox, checked whenever search is open. + var searchToggle = document.getElementById('__search'); + if (searchToggle && searchToggle.checked) { + return; + } if (isTypingTarget(document.activeElement)) { return; }