Skip to content

Commit c8be2ae

Browse files
committed
rustdoc: add three-column layout for large desktops
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.
1 parent a4518ea commit c8be2ae

File tree

9 files changed

+243
-73
lines changed

9 files changed

+243
-73
lines changed

src/librustdoc/html/static/css/rustdoc.css

+133-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
3434
</g></svg>');
3535
--button-left-margin: 4px;
3636
--button-border-radius: 2px;
37+
/* Used to manage the big screen three column layout */
38+
--width-limiter-width: 960px;
39+
--desktop-grid-column-gap: 45px;
40+
--container-border-radius: 6px;
41+
/* height of header, plus header margin, plus top logo section */
42+
--desktop-grid-toc-top: calc((1.25 * 1.5rem) + 76px + 23px);
43+
--desktop-grid-toc-max-width: 512px;
3744
}
3845

3946
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -336,7 +343,7 @@ button#toggle-all-docs {
336343
main {
337344
position: relative;
338345
flex-grow: 1;
339-
padding: 10px 15px 40px 45px;
346+
padding: 10px 15px 40px var(--desktop-grid-column-gap);
340347
min-width: 0; /* avoid growing beyond the size limit */
341348
}
342349

@@ -345,7 +352,7 @@ main {
345352
}
346353

347354
.width-limiter {
348-
max-width: 960px;
355+
max-width: var(--width-limiter-width);
349356
margin-right: auto;
350357
}
351358

@@ -369,6 +376,7 @@ pre {
369376
}
370377
pre.item-decl {
371378
overflow-x: auto;
379+
border-radius: var(--container-border-radius);
372380
}
373381
/* This rule allows to have scrolling on the X axis. */
374382
.item-decl .type-contents-toggle {
@@ -460,7 +468,7 @@ img {
460468
.sidebar-resizing .sidebar {
461469
position: fixed;
462470
}
463-
.sidebar-resizing > body {
471+
.sidebar-resizing .rustdoc {
464472
padding-left: var(--resizing-sidebar-width);
465473
}
466474

@@ -534,7 +542,7 @@ img {
534542
scrollbar-width: initial;
535543
scrollbar-color: var(--scrollbar-color);
536544
}
537-
.sidebar {
545+
.sidebar, #rustdoc-toc section, #rustdoc-modnav section {
538546
scrollbar-width: thin;
539547
scrollbar-color: var(--scrollbar-color);
540548
}
@@ -543,17 +551,24 @@ img {
543551
::-webkit-scrollbar {
544552
width: 12px;
545553
}
546-
.sidebar::-webkit-scrollbar {
554+
.sidebar::-webkit-scrollbar,
555+
#rustdoc-toc section::-webkit-scrollbar,
556+
#rustdoc-modnav section::-webkit-scrollbar {
547557
width: 8px;
548558
}
549559
::-webkit-scrollbar-track {
550560
-webkit-box-shadow: inset 0;
551561
background-color: var(--scrollbar-track-background-color);
552562
}
553-
.sidebar::-webkit-scrollbar-track {
563+
.sidebar::-webkit-scrollbar-track,
564+
#rustdoc-toc section::-webkit-scrollbar-track,
565+
#rustdoc-modnav section::-webkit-scrollbar-track {
554566
background-color: var(--scrollbar-track-background-color);
555567
}
556-
::-webkit-scrollbar-thumb, .sidebar::-webkit-scrollbar-thumb {
568+
::-webkit-scrollbar-thumb,
569+
.sidebar::-webkit-scrollbar-thumb,
570+
#rustdoc-toc section::-webkit-scrollbar-thumb,
571+
#rustdoc-modnav section::-webkit-scrollbar-thumb {
557572
background-color: var(--scrollbar-thumb-background-color);
558573
}
559574

@@ -742,7 +757,7 @@ ul.block, .block li, .block ul {
742757
overflow-wrap: break-word;
743758
}
744759

745-
.sidebar-crate + .version {
760+
.sidebar > .version {
746761
margin-top: -1rem;
747762
margin-bottom: 1rem;
748763
}
@@ -758,7 +773,7 @@ ul.block, .block li, .block ul {
758773
}
759774

760775
.rustdoc .example-wrap > pre {
761-
border-radius: 6px;
776+
border-radius: var(--container-border-radius);
762777
}
763778

764779
/* For the last child of a div, the margin will be taken care of
@@ -2006,6 +2021,115 @@ However, it's not needed with smaller screen width because the doc/code block is
20062021

20072022
/* Media Queries */
20082023

2024+
/* Very-large-screen mode. */
2025+
@supports (display: grid) and (display: contents) {
2026+
@media (min-width: 1600px) {
2027+
.rustdoc:not(.src) {
2028+
display: grid;
2029+
grid-template-columns:
2030+
var(--desktop-sidebar-width)
2031+
var(--width-limiter-width)
2032+
minmax(0, 1fr);
2033+
grid-template-rows: min-content 1fr;
2034+
grid-template-areas:
2035+
"sidebar-title main sidebar-cratenav"
2036+
"sidebar-modnav main sidebar-toc";
2037+
grid-column-gap: var(--desktop-grid-column-gap);
2038+
}
2039+
.sidebar-resizing .rustdoc:not(.src) {
2040+
padding-left: 0;
2041+
}
2042+
.hide-sidebar .rustdoc:not(.src) {
2043+
grid-template-columns:
2044+
var(--width-limiter-width)
2045+
minmax(0, 1fr);
2046+
grid-template-rows: minmax(min-content, calc(64px + 0.75rem)) 1fr;
2047+
grid-template-areas:
2048+
"main sidebar-cratenav"
2049+
"main sidebar-toc";
2050+
padding-left: var(--desktop-grid-column-gap);
2051+
}
2052+
.rustdoc:not(.src) .sidebar,
2053+
.rustdoc:not(.src) main {
2054+
display: contents;
2055+
}
2056+
.width-limiter {
2057+
grid-area: main;
2058+
width: var(--width-limiter-width);
2059+
--desktop-sidebar-width: 0;
2060+
}
2061+
.rustdoc:not(.src) nav.sub {
2062+
padding-top: 10px;
2063+
}
2064+
.rustdoc:not(.src) .doc-sidebar-title {
2065+
grid-area: sidebar-title;
2066+
background: var(--sidebar-background-color);
2067+
position: sticky;
2068+
top: 0;
2069+
}
2070+
.rustdoc:not(.src) .sidebar-crate {
2071+
margin-bottom: 0.5rem;
2072+
}
2073+
.rustdoc:not(.src) #rustdoc-toc,
2074+
.rustdoc:not(.src) #rustdoc-cratenav {
2075+
grid-area: sidebar-toc;
2076+
background: var(--main-background-color);
2077+
padding-left: 0;
2078+
}
2079+
.rustdoc:not(.src) #rustdoc-cratenav {
2080+
grid-area: sidebar-cratenav;
2081+
align-self: middle;
2082+
}
2083+
.rustdoc:not(.src) #rustdoc-modnav {
2084+
grid-area: sidebar-modnav;
2085+
background: var(--sidebar-background-color);
2086+
padding-left: 0;
2087+
}
2088+
.rustdoc:not(.src) #rustdoc-modnav .in-crate {
2089+
display: none;
2090+
}
2091+
.rustdoc:not(.src) #rustdoc-toc section,
2092+
.rustdoc:not(.src) #rustdoc-modnav section {
2093+
position: sticky;
2094+
top: 0;
2095+
bottom: 0;
2096+
overflow-y: scroll;
2097+
overscroll-behavior: contain;
2098+
max-height: 100vh;
2099+
padding-left: 24px;
2100+
}
2101+
.rustdoc:not(.src) #rustdoc-toc .location,
2102+
.rustdoc:not(.src) #rustdoc-modnav h2 {
2103+
margin-top: 0;
2104+
}
2105+
.rustdoc:not(.src) #rustdoc-modnav section {
2106+
top: calc(64px + 0.75rem);
2107+
height: calc(100vh - 64px - 0.75rem);
2108+
background: var(--sidebar-background-color);
2109+
}
2110+
.rustdoc:not(.src) #rustdoc-modnav section.scrolled {
2111+
border-top: solid 1px var(--border-color);
2112+
}
2113+
.rustdoc:not(.src) #rustdoc-toc section {
2114+
max-height: calc(100vh - (2 * var(--desktop-grid-toc-top)));
2115+
top: var(--desktop-grid-toc-top);
2116+
margin: 0 var(--desktop-grid-column-gap) var(--desktop-grid-column-gap) 0;
2117+
border: solid 1px var(--border-color);
2118+
padding: 14px 0 14px var(--sidebar-elems-left-padding);
2119+
border-radius: var(--container-border-radius);
2120+
max-width: var(--desktop-grid-toc-max-width);
2121+
}
2122+
.rustdoc:not(.src) #rustdoc-cratenav .block:last-child,
2123+
.rustdoc:not(.src) #rustdoc-toc .block:last-child {
2124+
margin-bottom: 0;
2125+
}
2126+
.rustdoc:not(.src) #rustdoc-cratenav a:hover,
2127+
.rustdoc:not(.src) #rustdoc-toc a:hover {
2128+
background-color: var(--sidebar-background-color);
2129+
}
2130+
}
2131+
}
2132+
20092133
/* Make sure all the buttons line wrap at the same time */
20102134
@media (max-width: 850px) {
20112135
#search-tabs .count {

src/librustdoc/html/static/js/main.js

+26-4
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ function preLoadCss(cssUrl) {
493493
if (!window.SIDEBAR_ITEMS) {
494494
return;
495495
}
496-
const sidebar = document.getElementById("rustdoc-modnav");
496+
const sidebar = document.querySelector("#rustdoc-modnav section");
497497

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

1550+
// When running in grid layout mode, we have to change sizes
1551+
// on the parent element. Otherwise, we can resize the sidebar
1552+
// independently.
1553+
//
1554+
// This is less bad than it otherwise would be, since if you are in grid
1555+
// mode, resizing the sidebar will resize the floating TOC, not the huge
1556+
// content area.
1557+
let gridMode = window.getComputedStyle(document.querySelector(".rustdoc")).display === "grid";
1558+
1559+
// Scroll border between modnav and logo lockup (this is only used in gridmode).
1560+
const modNavSection = document.querySelector("#rustdoc-modnav section");
1561+
if (modNavSection) {
1562+
modNavSection.onscroll = function() {
1563+
(this.scrollTop === 0 ? removeClass : addClass)(this, "scrolled");
1564+
};
1565+
}
1566+
15491567
// Toolbar button to show the sidebar.
15501568
//
15511569
// On small, "mobile-sized" viewports, it's not persistent and it
@@ -1666,6 +1684,9 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
16661684
updateLocalStorage("desktop-sidebar-width", size);
16671685
sidebar.style.setProperty("--desktop-sidebar-width", size + "px");
16681686
resizer.style.setProperty("--desktop-sidebar-width", size + "px");
1687+
if (gridMode) {
1688+
document.documentElement.style.setProperty("--desktop-sidebar-width", size + "px");
1689+
}
16691690
}
16701691
}
16711692

@@ -1717,6 +1738,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
17171738
if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
17181739
return;
17191740
}
1741+
gridMode = window.getComputedStyle(document.querySelector(".rustdoc")).display === "grid";
17201742
stopResize();
17211743
if (desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
17221744
changeSidebarSize(window.innerWidth - BODY_MIN);

src/librustdoc/html/templates/page.html

+17-15
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,24 @@
8787
{% endif %}
8888
<nav class="sidebar"> {# #}
8989
{% if page.css_class != "src" %}
90-
<div class="sidebar-crate">
91-
{% if !layout.logo.is_empty() || page.rust_logo %}
92-
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
93-
{% if page.rust_logo %}
94-
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
95-
{% else if !layout.logo.is_empty() %}
96-
<img src="{{layout.logo}}" alt="logo"> {# #}
90+
<div class="doc-sidebar-title">
91+
<div class="sidebar-crate">
92+
{% if !layout.logo.is_empty() || page.rust_logo %}
93+
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
94+
{% if page.rust_logo %}
95+
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
96+
{% else if !layout.logo.is_empty() %}
97+
<img src="{{layout.logo}}" alt="logo"> {# #}
98+
{% endif %}
99+
</a> {# #}
97100
{% endif %}
98-
</a> {# #}
99-
{% endif %}
100-
<h2> {# #}
101-
<a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate|wrapped|safe}}</a> {# #}
102-
{% if !display_krate_version_number.is_empty() %}
103-
<span class="version">{{+ display_krate_version_number}}</span>
104-
{% endif %}
105-
</h2> {# #}
101+
<h2> {# #}
102+
<a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate|wrapped|safe}}</a> {# #}
103+
{% if !display_krate_version_number.is_empty() %}
104+
<span class="version">{{+ display_krate_version_number}}</span>
105+
{% endif %}
106+
</h2> {# #}
107+
</div> {# #}
106108
</div> {# #}
107109
{% if !display_krate_version_extra.is_empty() %}
108110
<div class="version">{{+ display_krate_version_extra}}</div> {# #}

src/librustdoc/html/templates/sidebar.html

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
<div class="sidebar-elems">
2-
{% if is_crate %}
3-
<ul class="block"> {# #}
1+
{% if is_crate %}
2+
<div class="sidebar-elems" id="rustdoc-cratenav">
3+
<ul class="block">
44
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
55
</ul>
6-
{% endif %}
7-
8-
{% if self.should_render_blocks() %}
9-
<section id="rustdoc-toc">
6+
</div>
7+
{% endif %}
8+
{% if self.should_render_blocks() %}
9+
<div class="sidebar-elems" id="rustdoc-toc">
10+
<section>
1011
{% if !title.is_empty() %}
1112
<h2 class="location"> {# #}
1213
<a href="#">{{title_prefix}}{{title|wrapped|safe}}</a> {# #}
@@ -52,12 +53,14 @@ <h3> {# #}
5253
{% endif %}
5354
{% endfor %}
5455
</section>
55-
{% endif %}
56-
<div id="rustdoc-modnav">
56+
</div>
57+
{% endif %}
58+
<div class="sidebar-elems" id="rustdoc-modnav">
59+
<section>
5760
{% if !path.is_empty() %}
5861
<h2{% if parent_is_crate +%} class="in-crate"{% endif %}> {# #}
5962
<a href="{% if is_mod %}../{% endif %}index.html">In {{+ path|wrapped|safe}}</a> {# #}
6063
</h2>
6164
{% endif %}
62-
</div> {# #}
65+
</section> {# #}
6366
</div>

0 commit comments

Comments
 (0)