Skip to content

Commit

Permalink
rustdoc: add three-column layout for large desktops
Browse files Browse the repository at this point in the history
This commit adds a floating TOC box to the right,
leaving the sibling/module/crate navigation on the left.

This kicks in at a size a little below 1920x1080, where
desktops with very wide monitors are: it's also around
the point where the content area can be full width while
allowing two sidebars. It only kicks in if the browser
supports grid layouts, but that should be most of them,
and we can't get rid of the two-column layout anyway,
since it's the layout you get on something like a portrait iPad.

This design, where it can be used, is meant to clearly split up
the table of contents and the site navigation, so the right
side floating box has the same color as the page while the left
sidebar does not. It also pushes it down further, so that it's
not as high as the search bar, though that's a bit more
subtle than the color.
  • Loading branch information
notriddle committed Jul 31, 2024
1 parent a4518ea commit 8c4f552
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 72 deletions.
132 changes: 124 additions & 8 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
</g></svg>');
--button-left-margin: 4px;
--button-border-radius: 2px;
--width-limiter-width: 960px;
--desktop-grid-column-gap: 45px;
}

/* See FiraSans-LICENSE.txt for the Fira Sans license. */
Expand Down Expand Up @@ -336,7 +338,7 @@ button#toggle-all-docs {
main {
position: relative;
flex-grow: 1;
padding: 10px 15px 40px 45px;
padding: 10px 15px 40px var(--desktop-grid-column-gap);
min-width: 0; /* avoid growing beyond the size limit */
}

Expand All @@ -345,7 +347,7 @@ main {
}

.width-limiter {
max-width: 960px;
max-width: var(--width-limiter-width);
margin-right: auto;
}

Expand Down Expand Up @@ -460,7 +462,7 @@ img {
.sidebar-resizing .sidebar {
position: fixed;
}
.sidebar-resizing > body {
.sidebar-resizing .rustdoc {
padding-left: var(--resizing-sidebar-width);
}

Expand Down Expand Up @@ -534,7 +536,7 @@ img {
scrollbar-width: initial;
scrollbar-color: var(--scrollbar-color);
}
.sidebar {
.sidebar, #rustdoc-toc section, #rustdoc-modnav section {
scrollbar-width: thin;
scrollbar-color: var(--scrollbar-color);
}
Expand All @@ -543,17 +545,24 @@ img {
::-webkit-scrollbar {
width: 12px;
}
.sidebar::-webkit-scrollbar {
.sidebar::-webkit-scrollbar,
#rustdoc-toc section::-webkit-scrollbar,
#rustdoc-modnav section::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0;
background-color: var(--scrollbar-track-background-color);
}
.sidebar::-webkit-scrollbar-track {
.sidebar::-webkit-scrollbar-track,
#rustdoc-toc section::-webkit-scrollbar-track,
#rustdoc-modnav section::-webkit-scrollbar-track {
background-color: var(--scrollbar-track-background-color);
}
::-webkit-scrollbar-thumb, .sidebar::-webkit-scrollbar-thumb {
::-webkit-scrollbar-thumb,
.sidebar::-webkit-scrollbar-thumb,
#rustdoc-toc section::-webkit-scrollbar-thumb,
#rustdoc-modnav section::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb-background-color);
}

Expand Down Expand Up @@ -742,7 +751,7 @@ ul.block, .block li, .block ul {
overflow-wrap: break-word;
}

.sidebar-crate + .version {
.sidebar > .version {
margin-top: -1rem;
margin-bottom: 1rem;
}
Expand Down Expand Up @@ -2006,6 +2015,113 @@ However, it's not needed with smaller screen width because the doc/code block is

/* Media Queries */

/* Very-large-screen mode. */
@supports (display: grid) and (display: contents) {
@media (min-width: 1600px) and (min-height: 800px) {
.rustdoc:not(.src) {
display: grid;
grid-template-columns:
var(--desktop-sidebar-width)
var(--width-limiter-width)
minmax(0, 1fr);
grid-template-rows: min-content 1fr;
grid-template-areas:
"sidebar-title main sidebar-cratenav"
"sidebar-modnav main sidebar-toc";
grid-column-gap: var(--desktop-grid-column-gap);
}
.sidebar-resizing .rustdoc:not(.src) {
padding-left: 0;
}
.hide-sidebar .rustdoc:not(.src) {
grid-template-columns:
var(--width-limiter-width)
minmax(0, 1fr);
grid-template-rows: minmax(min-content, calc(64px + 0.75rem)) 1fr;
grid-template-areas:
"main sidebar-cratenav"
"main sidebar-toc";
padding-left: var(--desktop-grid-column-gap);
}
.rustdoc:not(.src) .sidebar,
.rustdoc:not(.src) main {
display: contents;
}
.width-limiter {
grid-area: main;
width: var(--width-limiter-width);
--desktop-sidebar-width: 0;
}
.rustdoc:not(.src) nav.sub {
padding-top: 10px;
}
.rustdoc:not(.src) .doc-sidebar-title {
grid-area: sidebar-title;
background: var(--sidebar-background-color);
position: sticky;
top: 0;
}
.rustdoc:not(.src) .sidebar-crate {
margin-bottom: 0.5rem;
}
.rustdoc:not(.src) #rustdoc-toc,
.rustdoc:not(.src) #rustdoc-cratenav {
grid-area: sidebar-toc;
background: var(--main-background-color);
padding-left: 0;
}
.rustdoc:not(.src) #rustdoc-cratenav {
grid-area: sidebar-cratenav;
align-self: middle;
}
.rustdoc:not(.src) #rustdoc-modnav {
grid-area: sidebar-modnav;
background: var(--sidebar-background-color);
padding-left: 0;
}
.rustdoc:not(.src) #rustdoc-modnav .in-crate {
display: none;
}
.rustdoc:not(.src) #rustdoc-toc section,
.rustdoc:not(.src) #rustdoc-modnav section {
position: sticky;
top: 0;
bottom: 0;
overflow-y: scroll;
overscroll-behavior: contain;
max-height: 100vh;
padding-left: 24px;
}
.rustdoc:not(.src) #rustdoc-toc .location,
.rustdoc:not(.src) #rustdoc-modnav h2 {
margin-top: 0;
}
.rustdoc:not(.src) #rustdoc-modnav section {
top: calc(64px + 0.75rem);
height: calc(100vh - 64px - 0.75rem);
background: var(--sidebar-background-color);
}
.rustdoc:not(.src) #rustdoc-modnav section.scrolled {
border-top: solid 1px var(--border-color);
}
.rustdoc:not(.src) #rustdoc-toc section {
max-height: calc(100vh - 0.5rem);
top: 0.25rem;
margin: 0 var(--desktop-grid-column-gap) var(--desktop-grid-column-gap) 0;
border: solid 1px var(--border-color);
padding: 0.25rem;
}
.rustdoc:not(.src) #rustdoc-cratenav .block:last-child,
.rustdoc:not(.src) #rustdoc-toc .block:last-child {
margin-bottom: 0;
}
.rustdoc:not(.src) #rustdoc-cratenav a:hover,
.rustdoc:not(.src) #rustdoc-toc a:hover {
background-color: var(--sidebar-background-color);
}
}
}

/* Make sure all the buttons line wrap at the same time */
@media (max-width: 850px) {
#search-tabs .count {
Expand Down
30 changes: 26 additions & 4 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ function preLoadCss(cssUrl) {
if (!window.SIDEBAR_ITEMS) {
return;
}
const sidebar = document.getElementById("rustdoc-modnav");
const sidebar = document.querySelector("#rustdoc-modnav section");

/**
* Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
Expand Down Expand Up @@ -533,8 +533,9 @@ function preLoadCss(cssUrl) {
const li = document.createElement("li");
// Don't "optimize" this to just use `path`.
// We want the browser to normalize this into an absolute URL.
if (link.href === current_page) {
li.classList.add("current");
if (link.href.toString() === current_page) {
link.className = "current";
li.className = "current";
}
li.appendChild(link);
ul.appendChild(li);
Expand Down Expand Up @@ -880,7 +881,7 @@ function preLoadCss(cssUrl) {
if (!window.ALL_CRATES) {
return;
}
const sidebarElems = document.getElementById("rustdoc-modnav");
const sidebarElems = document.querySelector("#rustdoc-modnav section");
if (!sidebarElems) {
return;
}
Expand Down Expand Up @@ -1546,6 +1547,23 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
// At half-way past the minimum size, vanish the sidebar entirely
const SIDEBAR_VANISH_THRESHOLD = SIDEBAR_MIN / 2;

// When running in grid layout mode, we have to change sizes
// on the parent element. Otherwise, we can resize the sidebar
// independently.
//
// This is less bad than it otherwise would be, since if you are in grid
// mode, resizing the sidebar will resize the floating TOC, not the huge
// content area.
let gridMode = window.getComputedStyle(document.querySelector(".rustdoc")).display === "grid";

// Scroll border between modnav and logo lockup (this is only used in gridmode).
const modNavSection = document.querySelector("#rustdoc-modnav section");
if (modNavSection) {
modNavSection.onscroll = function() {
(this.scrollTop === 0 ? removeClass : addClass)(this, "scrolled");
};
}

// Toolbar button to show the sidebar.
//
// On small, "mobile-sized" viewports, it's not persistent and it
Expand Down Expand Up @@ -1666,6 +1684,9 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
updateLocalStorage("desktop-sidebar-width", size);
sidebar.style.setProperty("--desktop-sidebar-width", size + "px");
resizer.style.setProperty("--desktop-sidebar-width", size + "px");
if (gridMode) {
document.documentElement.style.setProperty("--desktop-sidebar-width", size + "px");
}
}
}

Expand Down Expand Up @@ -1717,6 +1738,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
return;
}
gridMode = window.getComputedStyle(document.querySelector(".rustdoc")).display === "grid";
stopResize();
if (desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
changeSidebarSize(window.innerWidth - BODY_MIN);
Expand Down
32 changes: 17 additions & 15 deletions src/librustdoc/html/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,24 @@
{% endif %}
<nav class="sidebar"> {# #}
{% if page.css_class != "src" %}
<div class="sidebar-crate">
{% if !layout.logo.is_empty() || page.rust_logo %}
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
{% if page.rust_logo %}
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
{% else if !layout.logo.is_empty() %}
<img src="{{layout.logo}}" alt="logo"> {# #}
<div class="doc-sidebar-title">
<div class="sidebar-crate">
{% if !layout.logo.is_empty() || page.rust_logo %}
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
{% if page.rust_logo %}
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
{% else if !layout.logo.is_empty() %}
<img src="{{layout.logo}}" alt="logo"> {# #}
{% endif %}
</a> {# #}
{% endif %}
</a> {# #}
{% endif %}
<h2> {# #}
<a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate|wrapped|safe}}</a> {# #}
{% if !display_krate_version_number.is_empty() %}
<span class="version">{{+ display_krate_version_number}}</span>
{% endif %}
</h2> {# #}
<h2> {# #}
<a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate|wrapped|safe}}</a> {# #}
{% if !display_krate_version_number.is_empty() %}
<span class="version">{{+ display_krate_version_number}}</span>
{% endif %}
</h2> {# #}
</div> {# #}
</div> {# #}
{% if !display_krate_version_extra.is_empty() %}
<div class="version">{{+ display_krate_version_extra}}</div> {# #}
Expand Down
23 changes: 13 additions & 10 deletions src/librustdoc/html/templates/sidebar.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<div class="sidebar-elems">
{% if is_crate %}
<ul class="block"> {# #}
{% if is_crate %}
<div class="sidebar-elems" id="rustdoc-cratenav">
<ul class="block">
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
</ul>
{% endif %}

{% if self.should_render_blocks() %}
<section id="rustdoc-toc">
</div>
{% endif %}
{% if self.should_render_blocks() %}
<div class="sidebar-elems" id="rustdoc-toc">
<section>
{% if !title.is_empty() %}
<h2 class="location"> {# #}
<a href="#">{{title_prefix}}{{title|wrapped|safe}}</a> {# #}
Expand Down Expand Up @@ -52,12 +53,14 @@ <h3> {# #}
{% endif %}
{% endfor %}
</section>
{% endif %}
<div id="rustdoc-modnav">
</div>
{% endif %}
<div class="sidebar-elems" id="rustdoc-modnav">
<section>
{% if !path.is_empty() %}
<h2{% if parent_is_crate +%} class="in-crate"{% endif %}> {# #}
<a href="{% if is_mod %}../{% endif %}index.html">In {{+ path|wrapped|safe}}</a> {# #}
</h2>
{% endif %}
</div> {# #}
</section> {# #}
</div>
12 changes: 6 additions & 6 deletions tests/rustdoc-gui/sidebar-modnav-position.goml
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,26 @@ define-function: (
block {
go-to: "file://" + |DOC_PATH| + |url|
// Checking results colors.
assert-position: ("#rustdoc-modnav > h2", {"x": |h2_x|, "y": |h2_y|})
assert-position: ("#rustdoc-modnav > section > h2", {"x": |h2_x|, "y": |h2_y|})
assert-position: (
"#rustdoc-modnav > ul:first-of-type > li:first-of-type",
"#rustdoc-modnav > section > ul:first-of-type > li:first-of-type",
{"x": |x|, "y": |y|}
)
},
)

// First, at test_docs root
go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
store-position: ("#rustdoc-modnav > h2", {"x": h2_x, "y": h2_y})
store-position: ("#rustdoc-modnav > ul:first-of-type > li:first-of-type", {"x": x, "y": y})
store-position: ("#rustdoc-modnav > section > h2", {"x": h2_x, "y": h2_y})
store-position: ("#rustdoc-modnav > section > ul:first-of-type > li:first-of-type", {"x": x, "y": y})
call-function: ("check-positions", {"url": "/test_docs/enum.WhoLetTheDogOut.html"})
call-function: ("check-positions", {"url": "/test_docs/struct.StructWithPublicUndocumentedFields.html"})
call-function: ("check-positions", {"url": "/test_docs/codeblock_sub/index.html"})

// Now in a submodule
go-to: "file://" + |DOC_PATH| + "/test_docs/fields/struct.Struct.html"
store-position: ("#rustdoc-modnav > h2", {"x": h2_x, "y": h2_y})
store-position: ("#rustdoc-modnav > ul:first-of-type > li:first-of-type", {"x": x, "y": y})
store-position: ("#rustdoc-modnav > section > h2", {"x": h2_x, "y": h2_y})
store-position: ("#rustdoc-modnav > section > ul:first-of-type > li:first-of-type", {"x": x, "y": y})
call-function: ("check-positions", {"url": "/test_docs/fields/struct.Struct.html"})
call-function: ("check-positions", {"url": "/test_docs/fields/union.Union.html"})
call-function: ("check-positions", {"url": "/test_docs/fields/enum.Enum.html"})
Loading

0 comments on commit 8c4f552

Please sign in to comment.