diff --git a/src/front-end/css/chrome.css b/src/front-end/css/chrome.css index 507a6056d9..360a653727 100644 --- a/src/front-end/css/chrome.css +++ b/src/front-end/css/chrome.css @@ -656,3 +656,46 @@ html:not(.sidebar-resizing) .sidebar { margin-inline-start: -14px; width: 14px; } + +/* The container for the help popup that covers the whole window. */ +#mdbook-help-container { + /* Position and size for the whole window. */ + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + /* This uses flex layout (which is set in book.js), and centers the popup + in the window.*/ + display: none; + align-items: center; + justify-content: center; + z-index: 1000; + /* Dim out the book while the popup is visible. */ + background: var(--overlay-bg); +} + +/* The popup help box. */ +#mdbook-help-popup { + box-shadow: 0 4px 24px rgba(0,0,0,0.15); + min-width: 300px; + max-width: 500px; + width: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + background-color: var(--bg); + color: var(--fg); + border-width: 1px; + border-color: var(--theme-popup-border); + border-style: solid; + border-radius: 8px; + padding: 10px; +} + +.mdbook-help-title { + text-align: center; + /* mdbook's margin for h2 is way too large. */ + margin: 10px; +} diff --git a/src/front-end/css/variables.css b/src/front-end/css/variables.css index 43eb9e0c51..5742d24142 100644 --- a/src/front-end/css/variables.css +++ b/src/front-end/css/variables.css @@ -64,6 +64,8 @@ --copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%); --footnote-highlight: #2668a6; + + --overlay-bg: rgba(33, 40, 48, 0.4); } .coal { @@ -115,6 +117,8 @@ --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); } .light, html:not(.js) { @@ -166,6 +170,8 @@ --copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%); --footnote-highlight: #7e7eff; + + --overlay-bg: rgba(200, 200, 205, 0.4); } .navy { @@ -217,6 +223,8 @@ --copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%); --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); } .rust { @@ -266,6 +274,8 @@ --copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%); --footnote-highlight: #d3a17a; + + --overlay-bg: rgba(150, 150, 150, 0.25); } @media (prefers-color-scheme: dark) { diff --git a/src/front-end/js/book.js b/src/front-end/js/book.js index e54da6a0dd..5df2096f7c 100644 --- a/src/front-end/js/book.js +++ b/src/front-end/js/book.js @@ -623,7 +623,7 @@ aria-label="Show hidden lines">'; (function chapterNavigation() { document.addEventListener('keydown', function(e) { - if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { + if (e.altKey || e.ctrlKey || e.metaKey) { return; } if (window.search && window.search.hasFocus()) { @@ -643,6 +643,55 @@ aria-label="Show hidden lines">'; window.location.href = previousButton.href; } } + function showHelp() { + const container = document.getElementById('mdbook-help-container'); + const overlay = document.getElementById('mdbook-help-popup'); + container.style.display = 'flex'; + + // Clicking outside the popup will dismiss it. + const mouseHandler = event => { + if (overlay.contains(event.target)) { + return; + } + if (event.button !== 0) { + return; + } + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('mousedown', mouseHandler); + hideHelp(); + }; + + // Pressing esc will dismiss the popup. + const escapeKeyHandler = event => { + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('keydown', escapeKeyHandler, true); + hideHelp(); + } + }; + document.addEventListener('keydown', escapeKeyHandler, true); + document.getElementById('mdbook-help-container') + .addEventListener('mousedown', mouseHandler); + } + function hideHelp() { + document.getElementById('mdbook-help-container').style.display = 'none'; + } + + // Usually needs the Shift key to be pressed + switch (e.key) { + case '?': + e.preventDefault(); + showHelp(); + break; + } + + // Rest of the keys are only active when the Shift key is not pressed + if (e.shiftKey) { + return; + } + switch (e.key) { case 'ArrowRight': e.preventDefault(); diff --git a/src/front-end/searcher/searcher.js b/src/front-end/searcher/searcher.js index 476c17e4cc..6dca596512 100644 --- a/src/front-end/searcher/searcher.js +++ b/src/front-end/searcher/searcher.js @@ -33,13 +33,7 @@ window.search = window.search || {}; mark_exclude = ['text'], marker = new Mark(content), URL_SEARCH_PARAM = 'search', - URL_MARK_PARAM = 'highlight', - - SEARCH_HOTKEY_KEYCODES = [83, 191], // `s` or `/`. - ESCAPE_KEYCODE = 27, - DOWN_KEYCODE = 40, - UP_KEYCODE = 38, - SELECT_KEYCODE = 13; + URL_MARK_PARAM = 'highlight'; let current_searchterm = '', doc_urls = [], @@ -352,7 +346,7 @@ window.search = window.search || {}; return; } - if (e.keyCode === ESCAPE_KEYCODE) { + if (e.key === 'Escape') { e.preventDefault(); searchbar.classList.remove('active'); setSearchUrlParameters('', @@ -362,38 +356,38 @@ window.search = window.search || {}; } showSearch(false); marker.unmark(); - } else if (!hasFocus() && SEARCH_HOTKEY_KEYCODES.includes(e.keyCode)) { + } else if (!hasFocus() && (e.key === 'S' || e.key === '/')) { e.preventDefault(); showSearch(true); window.scrollTo(0, 0); searchbar.select(); - } else if (hasFocus() && (e.keyCode === DOWN_KEYCODE - || e.keyCode === SELECT_KEYCODE)) { + } else if (hasFocus() && (e.key === 'ArrowDown' + || e.key === 'Enter')) { e.preventDefault(); const first = searchresults.firstElementChild; if (first !== null) { unfocusSearchbar(); first.classList.add('focus'); - if (e.keyCode === SELECT_KEYCODE) { + if (e.key === 'Enter') { window.location.assign(first.querySelector('a')); } } - } else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE - || e.keyCode === UP_KEYCODE - || e.keyCode === SELECT_KEYCODE)) { + } else if (!hasFocus() && (e.key === 'ArrowDown' + || e.key === 'ArrowUp' + || e.key === 'Enter')) { // not `:focus` because browser does annoying scrolling const focused = searchresults.querySelector('li.focus'); if (!focused) { return; } e.preventDefault(); - if (e.keyCode === DOWN_KEYCODE) { + if (e.key === 'ArrowDown') { const next = focused.nextElementSibling; if (next) { focused.classList.remove('focus'); next.classList.add('focus'); } - } else if (e.keyCode === UP_KEYCODE) { + } else if (e.key === 'ArrowUp') { focused.classList.remove('focus'); const prev = focused.previousElementSibling; if (prev) { @@ -401,7 +395,7 @@ window.search = window.search || {}; } else { searchbar.select(); } - } else { // SELECT_KEYCODE + } else { // Enter window.location.assign(focused.querySelector('a')); } } diff --git a/src/front-end/templates/index.hbs b/src/front-end/templates/index.hbs index ca3c73fba4..aeae9a843f 100644 --- a/src/front-end/templates/index.hbs +++ b/src/front-end/templates/index.hbs @@ -63,6 +63,19 @@
+Press ← or → to navigate between chapters
+ {{#if search_enabled}} +Press S or / to search in the book
+ {{/if}} +Press ? to show this help
+Press Esc to hide this help
+