Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc: improve scroll locking in the rustdoc mobile sidebars #98775

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ function loadCss(cssFileName) {

function onHashChange(ev) {
// If we're in mobile mode, we should hide the sidebar in any case.
const sidebar = document.getElementsByClassName("sidebar")[0];
removeClass(sidebar, "shown");
hideSidebar();
handleHashes(ev);
}

Expand Down Expand Up @@ -731,11 +730,50 @@ function loadCss(cssFileName) {
});
}());

let oldSidebarScrollPosition = null;

function showSidebar() {
if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
// This is to keep the scroll position on mobile.
oldSidebarScrollPosition = window.scrollY;
document.body.style.width = `${document.body.offsetWidth}px`;
document.body.style.position = "fixed";
document.body.style.top = `-${oldSidebarScrollPosition}px`;
document.querySelector(".mobile-topbar").style.top = `${oldSidebarScrollPosition}px`;
document.querySelector(".mobile-topbar").style.position = "relative";
} else {
oldSidebarScrollPosition = null;
}
const sidebar = document.getElementsByClassName("sidebar")[0];
addClass(sidebar, "shown");
}

function hideSidebar() {
if (oldSidebarScrollPosition !== null) {
// This is to keep the scroll position on mobile.
document.body.style.width = "";
document.body.style.position = "";
document.body.style.top = "";
document.querySelector(".mobile-topbar").style.top = "";
document.querySelector(".mobile-topbar").style.position = "";
// The scroll position is lost when resetting the style, hence why we store it in
// `oldSidebarScrollPosition`.
window.scrollTo(0, oldSidebarScrollPosition);
oldSidebarScrollPosition = null;
}
const sidebar = document.getElementsByClassName("sidebar")[0];
removeClass(sidebar, "shown");
}

window.addEventListener("resize", () => {
if (window.innerWidth >= window.RUSTDOC_MOBILE_BREAKPOINT &&
oldSidebarScrollPosition !== null) {
// If the user opens the sidebar in "mobile" mode, and then grows the browser window,
// we need to switch away from mobile mode and make the main content area scrollable.
hideSidebar();
}
});

function handleClick(id, f) {
const elem = document.getElementById(id);
if (elem) {
Expand Down Expand Up @@ -778,9 +816,9 @@ function loadCss(cssFileName) {
sidebar_menu_toggle.addEventListener("click", () => {
const sidebar = document.getElementsByClassName("sidebar")[0];
if (!hasClass(sidebar, "shown")) {
addClass(sidebar, "shown");
showSidebar();
} else {
removeClass(sidebar, "shown");
hideSidebar();
}
});
}
Expand Down
20 changes: 17 additions & 3 deletions src/librustdoc/html/static/js/source-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(function() {

const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
let oldScrollPosition = 0;
let oldScrollPosition = null;

function closeSidebarIfMobile() {
if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
Expand Down Expand Up @@ -71,25 +71,39 @@ function toggleSidebar() {
oldScrollPosition = window.scrollY;
document.body.style.position = "fixed";
document.body.style.top = `-${oldScrollPosition}px`;
} else {
oldScrollPosition = null;
}
addClass(document.documentElement, "source-sidebar-expanded");
child.innerText = "<";
updateLocalStorage("source-sidebar-show", "true");
} else {
if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT && oldScrollPosition !== null) {
// This is to keep the scroll position on mobile.
document.body.style.position = "";
document.body.style.top = "";
// The scroll position is lost when resetting the style, hence why we store it in
// `oldScroll`.
// `oldScrollPosition`.
window.scrollTo(0, oldScrollPosition);
oldScrollPosition = null;
}
removeClass(document.documentElement, "source-sidebar-expanded");
child.innerText = ">";
updateLocalStorage("source-sidebar-show", "false");
}
}

window.addEventListener("resize", () => {
notriddle marked this conversation as resolved.
Show resolved Hide resolved
if (window.innerWidth >= window.RUSTDOC_MOBILE_BREAKPOINT && oldScrollPosition !== null) {
// If the user opens the sidebar in "mobile" mode, and then grows the browser window,
// we need to switch away from mobile mode and make the main content area scrollable.
document.body.style.position = "";
document.body.style.top = "";
window.scrollTo(0, oldScrollPosition);
oldScrollPosition = null;
}
});

function createSidebarToggle() {
const sidebarToggle = document.createElement("div");
sidebarToggle.id = "sidebar-toggle";
Expand Down
31 changes: 31 additions & 0 deletions src/test/rustdoc-gui/sidebar-mobile-scroll.goml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This test ensures that the mobile sidebar preserves scroll position.
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
// Switching to "mobile view" by reducing the width to 600px.
size: (600, 600)
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})

// Scroll down.
scroll-to: "//h2[@id='blanket-implementations']"
assert-window-property: {"pageYOffset": "702"}

// Open the sidebar menu.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "0px"})

// We are no longer "scrolled". It's important that the user can't
// scroll the body at all, but these test scripts are run only in Chrome,
// and we need to use a more complicated solution to this problem because
// of Mobile Safari...
assert-window-property: {"pageYOffset": "0"}

// Close the sidebar menu. Make sure the scroll position gets restored.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "-1000px"})
assert-window-property: {"pageYOffset": "702"}

// Now test that scrollability returns when the browser window is just resized.
notriddle marked this conversation as resolved.
Show resolved Hide resolved
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "0px"})
assert-window-property: {"pageYOffset": "0"}
size: (900, 900)
assert-window-property: {"pageYOffset": "702"}
11 changes: 11 additions & 0 deletions src/test/rustdoc-gui/sidebar-source-code-display.goml
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,17 @@ wait-for-css: (".sidebar", {"width": "0px"})
// The "scrollTop" property should be the same.
assert-window-property: {"pageYOffset": "2519"}

// We now check that the scroll position is restored if the window is resized.
size: (500, 700)
click: "#sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
assert-window-property: {"pageYOffset": "0"}
size: (900, 900)
assert-window-property: {"pageYOffset": "2519"}
size: (500, 700)
click: "#sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "hidden"})

// We now check that opening the sidebar and clicking a link will close it.
// The behavior here on mobile is different than the behavior on desktop,
// but common sense dictates that if you have a list of files that fills the entire screen, and
Expand Down