Move help popup into a pocket menu as well

This commit is contained in:
Guillaume Gomez 2022-06-20 16:28:52 +02:00
parent 10f4ce324b
commit cc4f804829
8 changed files with 173 additions and 159 deletions

View File

@ -979,42 +979,51 @@ table,
font-weight: normal; font-weight: normal;
} }
body.blur > :not(#help) { .popover {
filter: blur(8px); font-size: 1rem;
-webkit-filter: blur(8px); position: absolute;
opacity: .7; right: 0;
z-index: 2;
display: block;
margin-top: 7px;
border-radius: 3px;
border: 1px solid;
font-size: 1rem;
} }
#help { /* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
width: 100%; .popover::before {
height: 100vh; content: '';
position: fixed; position: absolute;
top: 0; right: 11px;
left: 0; border: solid;
display: flex; border-width: 1px 1px 0 0;
justify-content: center; display: inline-block;
align-items: center; padding: 4px;
transform: rotate(-45deg);
top: -5px;
} }
#help > div {
flex: 0 0 auto; #help-button .popover {
box-shadow: 0 0 6px rgba(0,0,0,.2); max-width: 600px;
width: 550px;
height: auto;
border: 1px solid;
} }
#help dt {
#help-button .popover::before {
right: 48px;
}
#help-button dt {
float: left; float: left;
clear: left; clear: left;
display: block; display: block;
margin-right: 0.5rem; margin-right: 0.5rem;
} }
#help span.top, #help span.bottom { #help-button span.top, #help-button span.bottom {
text-align: center; text-align: center;
display: block; display: block;
font-size: 1.125rem; font-size: 1.125rem;
} }
#help span.top { #help-button span.top {
text-align: center; text-align: center;
display: block; display: block;
margin: 10px 0; margin: 10px 0;
@ -1022,17 +1031,17 @@ body.blur > :not(#help) {
padding-bottom: 4px; padding-bottom: 4px;
margin-bottom: 6px; margin-bottom: 6px;
} }
#help span.bottom { #help-button span.bottom {
clear: both; clear: both;
border-top: 1px solid; border-top: 1px solid;
} }
#help dd { margin: 5px 35px; } .side-by-side {
#help .infos { padding-left: 0; } text-align: initial;
#help h1, #help h2 { margin-top: 0; } }
#help > div div { .side-by-side > div {
width: 50%; width: 50%;
float: left; float: left;
padding: 0 20px 20px 17px;; padding: 0 20px 20px 17px;
} }
.item-info .stab { .item-info .stab {
@ -1387,7 +1396,7 @@ pre.rust {
#copy-path { #copy-path {
height: 34px; height: 34px;
} }
#settings-menu > a, #help-button, #copy-path { #settings-menu > a, #help-button > button, #copy-path {
padding: 5px; padding: 5px;
width: 33px; width: 33px;
border: 1px solid; border: 1px solid;
@ -1397,9 +1406,8 @@ pre.rust {
#settings-menu { #settings-menu {
padding: 0; padding: 0;
} }
#settings-menu > a { #settings-menu > a, #help-button > button {
padding: 5px; padding: 5px;
width: 100%;
height: 100%; height: 100%;
display: block; display: block;
} }
@ -1416,7 +1424,7 @@ pre.rust {
animation: rotating 2s linear infinite; animation: rotating 2s linear infinite;
} }
#help-button { #help-button > button {
font-family: "Fira Sans", Arial, sans-serif; font-family: "Fira Sans", Arial, sans-serif;
text-align: center; text-align: center;
/* Rare exception to specifying font sizes in rem. Since this is acting /* Rare exception to specifying font sizes in rem. Since this is acting

View File

@ -86,27 +86,6 @@ input:checked + .slider:before {
display: block; display: block;
} }
div#settings {
position: absolute;
right: 0;
z-index: 1;
display: block;
margin-top: 7px;
border-radius: 3px;
border: 1px solid;
}
#settings .setting-line { #settings .setting-line {
margin: 1.2em 0.6em; margin: 1.2em 0.6em;
} }
/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
div#settings::before {
content: '';
position: absolute;
right: 11px;
border: solid;
border-width: 1px 1px 0 0;
display: inline-block;
padding: 4px;
transform: rotate(-45deg);
top: -5px;
}

View File

@ -5,7 +5,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
/* General structure and fonts */ /* General structure and fonts */
body, #settings-menu #settings, #settings-menu #settings::before { body, .popover, .popover::before {
background-color: #0f1419; background-color: #0f1419;
color: #c5c5c5; color: #c5c5c5;
} }
@ -567,7 +567,7 @@ kbd {
box-shadow: inset 0 -1px 0 #5c6773; box-shadow: inset 0 -1px 0 #5c6773;
} }
#settings-menu > a, #help-button { #settings-menu > a, #help-button > button {
border-color: #5c6773; border-color: #5c6773;
background-color: #0f1419; background-color: #0f1419;
color: #fff; color: #fff;
@ -577,7 +577,8 @@ kbd {
filter: invert(100); filter: invert(100);
} }
#settings-menu #settings, #settings-menu #settings::before { .popover, .popover::before,
#help-button span.top, #help-button span.bottom {
border-color: #5c6773; border-color: #5c6773;
} }
@ -592,7 +593,7 @@ kbd {
} }
#settings-menu > a:hover, #settings-menu > a:focus, #settings-menu > a:hover, #settings-menu > a:focus,
#help-button:hover, #help-button:focus { #help-button > button:hover, #help-button > button:focus {
border-color: #e0e0e0; border-color: #e0e0e0;
} }

View File

@ -1,4 +1,4 @@
body, #settings-menu #settings, #settings-menu #settings::before { body, .popover, .popover::before {
background-color: #353535; background-color: #353535;
color: #ddd; color: #ddd;
} }
@ -442,18 +442,19 @@ kbd {
box-shadow: inset 0 -1px 0 #c6cbd1; box-shadow: inset 0 -1px 0 #c6cbd1;
} }
#settings-menu > a, #help-button { #settings-menu > a, #help-button > button {
border-color: #e0e0e0; border-color: #e0e0e0;
background: #f0f0f0; background: #f0f0f0;
color: #000; color: #000;
} }
#settings-menu > a:hover, #settings-menu > a:focus, #settings-menu > a:hover, #settings-menu > a:focus,
#help-button:hover, #help-button:focus { #help-button > button:hover, #help-button > button:focus {
border-color: #ffb900; border-color: #ffb900;
} }
#settings-menu #settings, #settings-menu #settings::before { .popover, .popover::before,
#help-button span.top, #help-button span.bottom {
border-color: #d2d2d2; border-color: #d2d2d2;
} }

View File

@ -1,6 +1,6 @@
/* General structure and fonts */ /* General structure and fonts */
body, #settings-menu #settings, #settings-menu #settings::before { body, .popover, .popover::before {
background-color: white; background-color: white;
color: black; color: black;
} }
@ -427,17 +427,18 @@ kbd {
box-shadow: inset 0 -1px 0 #c6cbd1; box-shadow: inset 0 -1px 0 #c6cbd1;
} }
#settings-menu > a, #help-button { #settings-menu > a, #help-button > button {
border-color: #e0e0e0; border-color: #e0e0e0;
background-color: #fff; background-color: #fff;
} }
#settings-menu > a:hover, #settings-menu > a:focus, #settings-menu > a:hover, #settings-menu > a:focus,
#help-button:hover, #help-button:focus { #help-button > button:hover, #help-button > button:focus {
border-color: #717171; border-color: #717171;
} }
#settings-menu #settings, #settings-menu #settings::before { .popover, .popover::before,
#help-button span.top, #help-button span.bottom {
border-color: #DDDDDD; border-color: #DDDDDD;
} }

View File

@ -63,6 +63,24 @@ function showMain() {
removeClass(document.getElementById(MAIN_ID), "hidden"); removeClass(document.getElementById(MAIN_ID), "hidden");
} }
function elemIsInParent(elem, parent) {
while (elem && elem !== document.body) {
if (elem === parent) {
return true;
}
elem = elem.parentElement;
}
return false;
}
function blurHandler(event, parentElem, hideCallback) {
if (!elemIsInParent(document.activeElement, parentElem) &&
!elemIsInParent(event.relatedTarget, parentElem)
) {
hideCallback();
}
}
(function() { (function() {
window.rootPath = getVar("root-path"); window.rootPath = getVar("root-path");
window.currentCrate = getVar("current-crate"); window.currentCrate = getVar("current-crate");
@ -104,11 +122,16 @@ const MAIN_ID = "main-content";
const SETTINGS_BUTTON_ID = "settings-menu"; const SETTINGS_BUTTON_ID = "settings-menu";
const ALTERNATIVE_DISPLAY_ID = "alternative-display"; const ALTERNATIVE_DISPLAY_ID = "alternative-display";
const NOT_DISPLAYED_ID = "not-displayed"; const NOT_DISPLAYED_ID = "not-displayed";
const HELP_BUTTON_ID = "help-button";
function getSettingsButton() { function getSettingsButton() {
return document.getElementById(SETTINGS_BUTTON_ID); return document.getElementById(SETTINGS_BUTTON_ID);
} }
function getHelpButton() {
return document.getElementById(HELP_BUTTON_ID);
}
// Returns the current URL without any query parameter or hash. // Returns the current URL without any query parameter or hash.
function getNakedUrl() { function getNakedUrl() {
return window.location.href.split("?")[0].split("#")[0]; return window.location.href.split("?")[0].split("#")[0];
@ -381,55 +404,17 @@ function loadCss(cssFileName) {
openParentDetails(document.getElementById(id)); openParentDetails(document.getElementById(id));
} }
function getHelpElement(build) {
if (build) {
buildHelperPopup();
}
return document.getElementById("help");
}
/**
* Show the help popup.
*
* @param {boolean} display - Whether to show or hide the popup
* @param {Event} ev - The event that triggered this call
* @param {Element} [help] - The help element if it already exists
*/
function displayHelp(display, ev, help) {
if (display) {
help = help ? help : getHelpElement(true);
if (hasClass(help, "hidden")) {
ev.preventDefault();
removeClass(help, "hidden");
addClass(document.body, "blur");
}
} else {
// No need to build the help popup if we want to hide it in case it hasn't been
// built yet...
help = help ? help : getHelpElement(false);
if (help && !hasClass(help, "hidden")) {
ev.preventDefault();
addClass(help, "hidden");
removeClass(document.body, "blur");
}
}
}
function handleEscape(ev) { function handleEscape(ev) {
searchState.clearInputTimeout(); searchState.clearInputTimeout();
const help = getHelpElement(false); switchDisplayedElement(null);
if (help && !hasClass(help, "hidden")) { if (browserSupportsHistoryApi()) {
displayHelp(false, ev, help); history.replaceState(null, window.currentCrate + " - Rust",
} else { getNakedUrl() + window.location.hash);
switchDisplayedElement(null);
if (browserSupportsHistoryApi()) {
history.replaceState(null, window.currentCrate + " - Rust",
getNakedUrl() + window.location.hash);
}
ev.preventDefault();
} }
ev.preventDefault();
searchState.defocus(); searchState.defocus();
window.hideSettings(); window.hideSettings();
hideHelp();
} }
const disableShortcuts = getSettingValue("disable-shortcuts") === "true"; const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@ -453,7 +438,6 @@ function loadCss(cssFileName) {
case "s": case "s":
case "S": case "S":
displayHelp(false, ev);
ev.preventDefault(); ev.preventDefault();
searchState.focus(); searchState.focus();
break; break;
@ -465,7 +449,7 @@ function loadCss(cssFileName) {
break; break;
case "?": case "?":
displayHelp(true, ev); showHelp();
break; break;
default: default:
@ -796,9 +780,6 @@ function loadCss(cssFileName) {
elem.addEventListener("click", f); elem.addEventListener("click", f);
} }
} }
handleClick("help-button", ev => {
displayHelp(true, ev);
});
handleClick(MAIN_ID, () => { handleClick(MAIN_ID, () => {
hideSidebar(); hideSidebar();
}); });
@ -842,24 +823,16 @@ function loadCss(cssFileName) {
}); });
} }
let buildHelperPopup = () => { function helpBlurHandler(event) {
const popup = document.createElement("aside"); blurHandler(event, getHelpButton(), hideHelp);
addClass(popup, "hidden"); }
popup.id = "help";
popup.addEventListener("click", ev => {
if (ev.target === popup) {
// Clicked the blurred zone outside the help popup; dismiss help.
displayHelp(false, ev);
}
});
function buildHelpMenu() {
const book_info = document.createElement("span"); const book_info = document.createElement("span");
book_info.className = "top"; book_info.className = "top";
book_info.innerHTML = "You can find more information in \ book_info.innerHTML = "You can find more information in \
<a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>."; <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
const container = document.createElement("div");
const shortcuts = [ const shortcuts = [
["?", "Show this help dialog"], ["?", "Show this help dialog"],
["S", "Focus the search field"], ["S", "Focus the search field"],
@ -895,23 +868,86 @@ function loadCss(cssFileName) {
addClass(div_infos, "infos"); addClass(div_infos, "infos");
div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos; div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
container.appendChild(book_info);
container.appendChild(div_shortcuts);
container.appendChild(div_infos);
const rustdoc_version = document.createElement("span"); const rustdoc_version = document.createElement("span");
rustdoc_version.className = "bottom"; rustdoc_version.className = "bottom";
const rustdoc_version_code = document.createElement("code"); const rustdoc_version_code = document.createElement("code");
rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version"); rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
rustdoc_version.appendChild(rustdoc_version_code); rustdoc_version.appendChild(rustdoc_version_code);
const container = document.createElement("div");
container.className = "popover";
container.style.display = "none";
const side_by_side = document.createElement("div");
side_by_side.className = "side-by-side";
side_by_side.appendChild(div_shortcuts);
side_by_side.appendChild(div_infos);
container.appendChild(book_info);
container.appendChild(side_by_side);
container.appendChild(rustdoc_version); container.appendChild(rustdoc_version);
popup.appendChild(container); const help_button = getHelpButton();
insertAfter(popup, document.querySelector("main")); help_button.appendChild(container);
// So that it's only built once and then it'll do nothing when called!
buildHelperPopup = () => {}; container.onblur = helpBlurHandler;
}; container.onclick = event => {
event.preventDefault();
};
help_button.onblur = helpBlurHandler;
help_button.children[0].onblur = helpBlurHandler;
return container;
}
/**
* Returns the help menu element (not the button).
*
* @param {boolean} buildNeeded - If this argument is `false`, the help menu element won't be
* built if it doesn't exist.
*
* @return {HTMLElement}
*/
function getHelpMenu(buildNeeded) {
let menu = getHelpButton().querySelector(".popover");
if (!menu && buildNeeded) {
menu = buildHelpMenu();
}
return menu;
}
/**
* Show the help popup menu.
*/
function showHelp() {
const menu = getHelpMenu(true);
if (menu.style.display === "none") {
menu.style.display = "";
}
}
/**
* Hide the help popup menu.
*/
function hideHelp() {
const menu = getHelpMenu(false);
if (menu && menu.style.display !== "none") {
menu.style.display = "none";
}
}
document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => {
const target = event.target;
if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) {
return;
}
const menu = getHelpMenu(true);
if (menu.style.display !== "none") {
hideHelp();
} else {
showHelp();
}
});
setMobileTopbar(); setMobileTopbar();
addSidebarItems(); addSidebarItems();

View File

@ -1,6 +1,6 @@
// Local js definitions: // Local js definitions:
/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */ /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
/* global addClass, removeClass, onEach, onEachLazy */ /* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */ /* global MAIN_ID, getVar, getSettingsButton */
"use strict"; "use strict";
@ -209,6 +209,7 @@
const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`; const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
const el = document.createElement(elementKind); const el = document.createElement(elementKind);
el.id = "settings"; el.id = "settings";
el.className = "popover";
el.innerHTML = innerHTML; el.innerHTML = innerHTML;
if (isSettingsPage) { if (isSettingsPage) {
@ -226,23 +227,8 @@
settingsMenu.style.display = ""; settingsMenu.style.display = "";
} }
function elemIsInParent(elem, parent) { function settingsBlurHandler(event) {
while (elem && elem !== document.body) { blurHandler(event, getSettingsButton(), window.hideSettings);
if (elem === parent) {
return true;
}
elem = elem.parentElement;
}
return false;
}
function blurHandler(event) {
const settingsButton = getSettingsButton();
if (!elemIsInParent(document.activeElement, settingsButton) &&
!elemIsInParent(event.relatedTarget, settingsButton)
) {
window.hideSettings();
}
} }
if (isSettingsPage) { if (isSettingsPage) {
@ -268,12 +254,12 @@
displaySettings(); displaySettings();
} }
}; };
settingsButton.onblur = blurHandler; settingsButton.onblur = settingsBlurHandler;
settingsButton.querySelector("a").onblur = blurHandler; settingsButton.querySelector("a").onblur = settingsBlurHandler;
onEachLazy(settingsMenu.querySelectorAll("input"), el => { onEachLazy(settingsMenu.querySelectorAll("input"), el => {
el.onblur = blurHandler; el.onblur = settingsBlurHandler;
}); });
settingsMenu.onblur = blurHandler; settingsMenu.onblur = settingsBlurHandler;
} }
// We now wait a bit for the web browser to end re-computing the DOM... // We now wait a bit for the web browser to end re-computing the DOM...

View File

@ -119,7 +119,9 @@
spellcheck="false" {# -#} spellcheck="false" {# -#}
placeholder="Click or press S to search, ? for more options…" {# -#} placeholder="Click or press S to search, ? for more options…" {# -#}
type="search"> {#- -#} type="search"> {#- -#}
<button type="button" id="help-button" title="help">?</button> {#- -#} <div id="help-button" title="help" tabindex="-1"> {#- -#}
<button type="button">?</button> {#- -#}
</div> {#- -#}
<div id="settings-menu" tabindex="-1"> <div id="settings-menu" tabindex="-1">
<a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#} <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
<img width="22" height="22" alt="Change settings" {# -#} <img width="22" height="22" alt="Change settings" {# -#}