Skip to content

Commit 48a944a

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 2e8db5e commit 48a944a

File tree

9 files changed

+244
-74
lines changed

9 files changed

+244
-74
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
}
@@ -760,7 +775,7 @@ ul.block, .block li, .block ul {
760775
.rustdoc .example-wrap > pre,
761776
.rustdoc .scraped-example .src-line-numbers,
762777
.rustdoc .scraped-example .src-line-numbers > pre {
763-
border-radius: 6px;
778+
border-radius: var(--container-border-radius);
764779
}
765780

766781
/*
@@ -2078,6 +2093,115 @@ However, it's not needed with smaller screen width because the doc/code block is
20782093

20792094
/* Media Queries */
20802095

2096+
/* Very-large-screen mode. */
2097+
@supports (display: grid) and (display: contents) {
2098+
@media (min-width: 1600px) {
2099+
.rustdoc:not(.src) {
2100+
display: grid;
2101+
grid-template-columns:
2102+
var(--desktop-sidebar-width)
2103+
var(--width-limiter-width)
2104+
minmax(0, 1fr);
2105+
grid-template-rows: min-content 1fr;
2106+
grid-template-areas:
2107+
"sidebar-title main sidebar-cratenav"
2108+
"sidebar-modnav main sidebar-toc";
2109+
grid-column-gap: var(--desktop-grid-column-gap);
2110+
}
2111+
.sidebar-resizing .rustdoc:not(.src) {
2112+
padding-left: 0;
2113+
}
2114+
.hide-sidebar .rustdoc:not(.src) {
2115+
grid-template-columns:
2116+
var(--width-limiter-width)
2117+
minmax(0, 1fr);
2118+
grid-template-rows: minmax(min-content, calc(64px + 0.75rem)) 1fr;
2119+
grid-template-areas:
2120+
"main sidebar-cratenav"
2121+
"main sidebar-toc";
2122+
padding-left: var(--desktop-grid-column-gap);
2123+
}
2124+
.rustdoc:not(.src) .sidebar,
2125+
.rustdoc:not(.src) main {
2126+
display: contents;
2127+
}
2128+
.width-limiter {
2129+
grid-area: main;
2130+
width: var(--width-limiter-width);
2131+
--desktop-sidebar-width: 0;
2132+
}
2133+
.rustdoc:not(.src) nav.sub {
2134+
padding-top: 10px;
2135+
}
2136+
.rustdoc:not(.src) .doc-sidebar-title {
2137+
grid-area: sidebar-title;
2138+
background: var(--sidebar-background-color);
2139+
position: sticky;
2140+
top: 0;
2141+
}
2142+
.rustdoc:not(.src) .sidebar-crate {
2143+
margin-bottom: 0.5rem;
2144+
}
2145+
.rustdoc:not(.src) #rustdoc-toc,
2146+
.rustdoc:not(.src) #rustdoc-cratenav {
2147+
grid-area: sidebar-toc;
2148+
background: var(--main-background-color);
2149+
padding-left: 0;
2150+
}
2151+
.rustdoc:not(.src) #rustdoc-cratenav {
2152+
grid-area: sidebar-cratenav;
2153+
align-self: middle;
2154+
}
2155+
.rustdoc:not(.src) #rustdoc-modnav {
2156+
grid-area: sidebar-modnav;
2157+
background: var(--sidebar-background-color);
2158+
padding-left: 0;
2159+
}
2160+
.rustdoc:not(.src) #rustdoc-modnav .in-crate {
2161+
display: none;
2162+
}
2163+
.rustdoc:not(.src) #rustdoc-toc section,
2164+
.rustdoc:not(.src) #rustdoc-modnav section {
2165+
position: sticky;
2166+
top: 0;
2167+
bottom: 0;
2168+
overflow-y: scroll;
2169+
overscroll-behavior: contain;
2170+
max-height: 100vh;
2171+
padding-left: 24px;
2172+
}
2173+
.rustdoc:not(.src) #rustdoc-toc .location,
2174+
.rustdoc:not(.src) #rustdoc-modnav h2 {
2175+
margin-top: 0;
2176+
}
2177+
.rustdoc:not(.src) #rustdoc-modnav section {
2178+
top: calc(64px + 0.75rem);
2179+
height: calc(100vh - 64px - 0.75rem);
2180+
background: var(--sidebar-background-color);
2181+
}
2182+
.rustdoc:not(.src) #rustdoc-modnav section.scrolled {
2183+
border-top: solid 1px var(--border-color);
2184+
}
2185+
.rustdoc:not(.src) #rustdoc-toc section {
2186+
max-height: calc(100vh - (2 * var(--desktop-grid-toc-top)));
2187+
top: var(--desktop-grid-toc-top);
2188+
margin: 0 var(--desktop-grid-column-gap) var(--desktop-grid-column-gap) 0;
2189+
border: solid 1px var(--border-color);
2190+
padding: 14px 0 14px var(--sidebar-elems-left-padding);
2191+
border-radius: var(--container-border-radius);
2192+
max-width: var(--desktop-grid-toc-max-width);
2193+
}
2194+
.rustdoc:not(.src) #rustdoc-cratenav .block:last-child,
2195+
.rustdoc:not(.src) #rustdoc-toc .block:last-child {
2196+
margin-bottom: 0;
2197+
}
2198+
.rustdoc:not(.src) #rustdoc-cratenav a:hover,
2199+
.rustdoc:not(.src) #rustdoc-toc a:hover {
2200+
background-color: var(--sidebar-background-color);
2201+
}
2202+
}
2203+
}
2204+
20812205
/* Make sure all the buttons line wrap at the same time */
20822206
@media (max-width: 850px) {
20832207
#search-tabs .count {

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

+26-4
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ function preLoadCss(cssUrl) {
499499
if (!window.SIDEBAR_ITEMS) {
500500
return;
501501
}
502-
const sidebar = document.getElementById("rustdoc-modnav");
502+
const sidebar = document.querySelector("#rustdoc-modnav section");
503503

504504
/**
505505
* Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
@@ -539,8 +539,9 @@ function preLoadCss(cssUrl) {
539539
const li = document.createElement("li");
540540
// Don't "optimize" this to just use `path`.
541541
// We want the browser to normalize this into an absolute URL.
542-
if (link.href === current_page) {
543-
li.classList.add("current");
542+
if (link.href.toString() === current_page) {
543+
link.className = "current";
544+
li.className = "current";
544545
}
545546
li.appendChild(link);
546547
ul.appendChild(li);
@@ -885,7 +886,7 @@ function preLoadCss(cssUrl) {
885886
if (!window.ALL_CRATES) {
886887
return;
887888
}
888-
const sidebarElems = document.getElementById("rustdoc-modnav");
889+
const sidebarElems = document.querySelector("#rustdoc-modnav section");
889890
if (!sidebarElems) {
890891
return;
891892
}
@@ -1549,6 +1550,23 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
15491550
// At half-way past the minimum size, vanish the sidebar entirely
15501551
const SIDEBAR_VANISH_THRESHOLD = SIDEBAR_MIN / 2;
15511552

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

@@ -1720,6 +1741,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
17201741
if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
17211742
return;
17221743
}
1744+
gridMode = window.getComputedStyle(document.querySelector(".rustdoc")).display === "grid";
17231745
stopResize();
17241746
if (desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
17251747
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

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
<div class="sidebar-elems">
2-
{% if is_crate %}
1+
{% if is_crate %}
2+
<div class="sidebar-elems" id="rustdoc-cratenav"> {# #}
33
<ul class="block"> {# #}
44
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
5-
</ul>
6-
{% endif %}
7-
8-
{% if self.should_render_blocks() %}
9-
<section id="rustdoc-toc">
5+
</ul> {# #}
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> {# #}
@@ -51,13 +52,15 @@ <h3> {# #}
5152
{% endif %}
5253
{% endif %}
5354
{% endfor %}
54-
</section>
55-
{% endif %}
56-
<div id="rustdoc-modnav">
55+
</section> {# #}
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)