rustdoc: use CSS overscroll-behavior
instead of JavaScript
Fixes the desktop scrolling weirdness mentioned in https://github.com/rust-lang/rust/pull/98775#issuecomment-1182575603 As described in the MDN page for this property: * The current Firefox ESR is 102, and the first Firefox version to support this feature is 59. * The current Chrome version 112, and the first version to support this is 63. * Edge is described as having a minor bug in `none` mode, but we use `contain` mode anyway, so it doesn't matter. * Safari 16, released September 2022, is the last browser to add this feature, and is also the oldest version we officially support.
This commit is contained in:
parent
661b33f524
commit
bb7ed64f45
@ -384,6 +384,7 @@ img {
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
flex: 0 0 200px;
|
flex: 0 0 200px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
overscroll-behavior: contain;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -1531,7 +1532,7 @@ However, it's not needed with smaller screen width because the doc/code block is
|
|||||||
/*
|
/*
|
||||||
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||||
If you update this line, then you also need to update the line with the same warning
|
If you update this line, then you also need to update the line with the same warning
|
||||||
in main.js
|
in source-script.js
|
||||||
*/
|
*/
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
|
/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
|
||||||
|
@ -4,11 +4,6 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
|
||||||
// If you update this line, then you also need to update the media query with the same
|
|
||||||
// warning in rustdoc.css
|
|
||||||
window.RUSTDOC_MOBILE_BREAKPOINT = 700;
|
|
||||||
|
|
||||||
// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
|
// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
|
||||||
// for a resource under the root-path, with the resource-suffix.
|
// for a resource under the root-path, with the resource-suffix.
|
||||||
function resourcePath(basename, extension) {
|
function resourcePath(basename, extension) {
|
||||||
@ -730,65 +725,18 @@ function preLoadCss(cssUrl) {
|
|||||||
window.rustdoc_add_line_numbers_to_examples();
|
window.rustdoc_add_line_numbers_to_examples();
|
||||||
}
|
}
|
||||||
|
|
||||||
let oldSidebarScrollPosition = null;
|
|
||||||
|
|
||||||
// Scroll locking used both here and in source-script.js
|
|
||||||
|
|
||||||
window.rustdocMobileScrollLock = function() {
|
|
||||||
const mobile_topbar = document.querySelector(".mobile-topbar");
|
|
||||||
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`;
|
|
||||||
if (mobile_topbar) {
|
|
||||||
mobile_topbar.style.top = `${oldSidebarScrollPosition}px`;
|
|
||||||
mobile_topbar.style.position = "relative";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldSidebarScrollPosition = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.rustdocMobileScrollUnlock = function() {
|
|
||||||
const mobile_topbar = document.querySelector(".mobile-topbar");
|
|
||||||
if (oldSidebarScrollPosition !== null) {
|
|
||||||
// This is to keep the scroll position on mobile.
|
|
||||||
document.body.style.width = "";
|
|
||||||
document.body.style.position = "";
|
|
||||||
document.body.style.top = "";
|
|
||||||
if (mobile_topbar) {
|
|
||||||
mobile_topbar.style.top = "";
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function showSidebar() {
|
function showSidebar() {
|
||||||
window.hideAllModals(false);
|
window.hideAllModals(false);
|
||||||
window.rustdocMobileScrollLock();
|
|
||||||
const sidebar = document.getElementsByClassName("sidebar")[0];
|
const sidebar = document.getElementsByClassName("sidebar")[0];
|
||||||
addClass(sidebar, "shown");
|
addClass(sidebar, "shown");
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideSidebar() {
|
function hideSidebar() {
|
||||||
window.rustdocMobileScrollUnlock();
|
|
||||||
const sidebar = document.getElementsByClassName("sidebar")[0];
|
const sidebar = document.getElementsByClassName("sidebar")[0];
|
||||||
removeClass(sidebar, "shown");
|
removeClass(sidebar, "shown");
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("resize", () => {
|
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();
|
|
||||||
}
|
|
||||||
if (window.CURRENT_TOOLTIP_ELEMENT) {
|
if (window.CURRENT_TOOLTIP_ELEMENT) {
|
||||||
// As a workaround to the behavior of `contains: layout` used in doc togglers,
|
// As a workaround to the behavior of `contains: layout` used in doc togglers,
|
||||||
// tooltip popovers are positioned using javascript.
|
// tooltip popovers are positioned using javascript.
|
||||||
|
@ -15,8 +15,13 @@ const NAME_OFFSET = 0;
|
|||||||
const DIRS_OFFSET = 1;
|
const DIRS_OFFSET = 1;
|
||||||
const FILES_OFFSET = 2;
|
const FILES_OFFSET = 2;
|
||||||
|
|
||||||
|
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||||
|
// If you update this line, then you also need to update the media query with the same
|
||||||
|
// warning in rustdoc.css
|
||||||
|
const RUSTDOC_MOBILE_BREAKPOINT = 700;
|
||||||
|
|
||||||
function closeSidebarIfMobile() {
|
function closeSidebarIfMobile() {
|
||||||
if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
|
if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
|
||||||
updateLocalStorage("source-sidebar-show", "false");
|
updateLocalStorage("source-sidebar-show", "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,12 +74,10 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
|
|||||||
function toggleSidebar() {
|
function toggleSidebar() {
|
||||||
const child = this.parentNode.children[0];
|
const child = this.parentNode.children[0];
|
||||||
if (child.innerText === ">") {
|
if (child.innerText === ">") {
|
||||||
window.rustdocMobileScrollLock();
|
|
||||||
addClass(document.documentElement, "source-sidebar-expanded");
|
addClass(document.documentElement, "source-sidebar-expanded");
|
||||||
child.innerText = "<";
|
child.innerText = "<";
|
||||||
updateLocalStorage("source-sidebar-show", "true");
|
updateLocalStorage("source-sidebar-show", "true");
|
||||||
} else {
|
} else {
|
||||||
window.rustdocMobileScrollUnlock();
|
|
||||||
removeClass(document.documentElement, "source-sidebar-expanded");
|
removeClass(document.documentElement, "source-sidebar-expanded");
|
||||||
child.innerText = ">";
|
child.innerText = ">";
|
||||||
updateLocalStorage("source-sidebar-show", "false");
|
updateLocalStorage("source-sidebar-show", "false");
|
||||||
|
@ -1,31 +1,12 @@
|
|||||||
// This test ensures that the mobile sidebar preserves scroll position.
|
// This test ensures that the mobile disables scrolling the page.
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
|
||||||
// Switching to "mobile view" by reducing the width to 600px.
|
set-window-size: (1280, 800) // desktop
|
||||||
set-window-size: (700, 600)
|
assert-css: (".sidebar", {"overscroll-behavior": "contain"})
|
||||||
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
|
set-window-size: (700, 600) // mobile
|
||||||
|
assert-css: (".sidebar", {"overscroll-behavior": "contain"})
|
||||||
|
|
||||||
// Scroll down.
|
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||||
scroll-to: "//h2[@id='blanket-implementations']"
|
set-window-size: (1280, 800) // desktop
|
||||||
assert-window-property: {"pageYOffset": "622"}
|
assert-css: (".sidebar", {"overscroll-behavior": "contain"})
|
||||||
|
set-window-size: (700, 600) // mobile
|
||||||
// Open the sidebar menu.
|
assert-css: (".sidebar", {"overscroll-behavior": "contain"})
|
||||||
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": "622"}
|
|
||||||
|
|
||||||
// Now test that scrollability returns when the browser window is just resized.
|
|
||||||
click: ".sidebar-menu-toggle"
|
|
||||||
wait-for-css: (".sidebar", {"left": "0px"})
|
|
||||||
assert-window-property: {"pageYOffset": "0"}
|
|
||||||
set-window-size: (900, 600)
|
|
||||||
assert-window-property: {"pageYOffset": "622"}
|
|
||||||
|
@ -183,22 +183,12 @@ wait-for-css: (".sidebar", {"left": "-1000px"})
|
|||||||
// The "scrollTop" property should be the same.
|
// The "scrollTop" property should be the same.
|
||||||
assert-window-property: {"pageYOffset": "2542"}
|
assert-window-property: {"pageYOffset": "2542"}
|
||||||
|
|
||||||
// We now check that the scroll position is restored if the window is resized.
|
|
||||||
set-window-size: (500, 700)
|
|
||||||
click: "#src-sidebar-toggle"
|
|
||||||
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
|
|
||||||
assert-window-property: {"pageYOffset": "0"}
|
|
||||||
set-window-size: (900, 900)
|
|
||||||
assert-window-property: {"pageYOffset": "2542"}
|
|
||||||
set-window-size: (500, 700)
|
|
||||||
click: "#src-sidebar-toggle"
|
|
||||||
wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
|
|
||||||
|
|
||||||
// We now check that opening the sidebar and clicking a link will close it.
|
// 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,
|
// 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
|
// but common sense dictates that if you have a list of files that fills the entire screen, and
|
||||||
// you click one of them, you probably want to actually see the file's contents, and not just
|
// you click one of them, you probably want to actually see the file's contents, and not just
|
||||||
// make it the current selection.
|
// make it the current selection.
|
||||||
|
set-window-size: (500, 700)
|
||||||
click: "#src-sidebar-toggle"
|
click: "#src-sidebar-toggle"
|
||||||
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
|
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
|
||||||
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
|
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
|
||||||
|
Loading…
Reference in New Issue
Block a user