From 2852443f4877115c1c629d462cd83dae0baa7109 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 1 Jul 2022 10:33:06 -0700 Subject: [PATCH 1/5] rustdoc: use
tag for the source code sidebar This fixes the extremely poor accessibility of the old system, making it possible to navigate the sidebar by keyboard, and also implicitly gives the sidebar items the correct ARIA roles. --- src/librustdoc/html/static/css/rustdoc.css | 35 ++++------------ src/librustdoc/html/static/css/themes/ayu.css | 3 +- .../html/static/css/themes/dark.css | 3 +- .../html/static/css/themes/light.css | 3 +- .../html/static/js/source-script.js | 29 +++++-------- .../sidebar-source-code-display.goml | 42 +++++++++---------- src/test/rustdoc-gui/source-code-page.goml | 20 ++++----- 7 files changed, 53 insertions(+), 82 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 532b98d9bb9f6..7d5318a194c7d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1528,38 +1528,19 @@ kbd { margin-bottom: 1em; } -div.children { - padding-left: 27px; - display: none; -} -div.name { +details.dir-entry > summary { + margin: 0 0 0 13px; + list-style-position: outside; cursor: pointer; - position: relative; - margin-left: 16px; } -div.files > a { - display: block; - padding: 0 3px; -} -div.files > a:hover, div.name:hover { - background-color: #a14b4b; + +details.dir-entry div.folders, details.dir-entry div.files { + padding-left: 27px; } -div.name.expand + .children { + +details.dir-entry a { display: block; } -div.name::before { - content: "\25B6"; - padding-left: 4px; - font-size: 0.625rem; - position: absolute; - left: -16px; - top: 4px; -} -div.name.expand::before { - transform: rotate(90deg); - left: -15px; - top: 2px; -} /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index b7d0db1f0020f..a78ac5da7490b 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -630,7 +630,8 @@ kbd { color: #fff; border-bottom-color: #5c6773; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #14191f; color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index eb64ef3e7710b..a2abd53fa02bc 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -500,7 +500,8 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #444; } #source-sidebar div.files > .selected { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 00cdf83589716..c4510ad6ae66b 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -484,7 +484,8 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #E0E0E0; } #source-sidebar div.files > .selected { diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index acb1d8d7b5c8d..21c3609279075 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -13,33 +13,27 @@ const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-p let oldScrollPosition = 0; function createDirEntry(elem, parent, fullPath, hasFoundFile) { - const name = document.createElement("div"); - name.className = "name"; + const dirEntry = document.createElement("details"); + const summary = document.createElement("summary"); + + dirEntry.className = "dir-entry"; fullPath += elem["name"] + "/"; - name.onclick = ev => { - if (hasClass(ev.target, "expand")) { - removeClass(ev.target, "expand"); - } else { - addClass(ev.target, "expand"); - } - }; - name.innerText = elem["name"]; + summary.innerText = elem["name"]; + dirEntry.appendChild(summary); - const children = document.createElement("div"); - children.className = "children"; const folders = document.createElement("div"); folders.className = "folders"; if (elem.dirs) { for (const dir of elem.dirs) { if (createDirEntry(dir, folders, fullPath, hasFoundFile)) { - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } } } - children.appendChild(folders); + dirEntry.appendChild(folders); const files = document.createElement("div"); files.className = "files"; @@ -51,15 +45,14 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const w = window.location.href.split("#")[0]; if (!hasFoundFile && w === file.href) { file.className = "selected"; - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } files.appendChild(file); } } - children.appendChild(files); - parent.appendChild(name); - parent.appendChild(children); + dirEntry.appendChild(files); + parent.appendChild(dirEntry); return hasFoundFile; } diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index c441f84a82135..1d8cc22100c3d 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -27,29 +27,29 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) @@ -59,29 +59,29 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files > a.selected", {"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files > a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) @@ -91,29 +91,29 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index b45512601f208..05b0e809bca69 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -34,19 +34,13 @@ assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) click: "#sidebar-toggle" assert: ".source-sidebar-expanded" -// We check that the first entry of the sidebar is collapsed (which, for whatever reason, -// is number 2 and not 1...). -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-text: ("#source-sidebar .name:nth-child(2)", "implementors") -// We also check its children are hidden too. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +// We check that the first entry of the sidebar is collapsed +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) +assert-text: ("#source-sidebar details:first-of-type > summary", "implementors") // We now click on it. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name expand"}) -// Checking that its children are displayed as well. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "block"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) // And now we collapse it again. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) From 1f621fba2d7ef850b5d1920ef2bf37c7fa89570c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 1 Jul 2022 11:27:09 -0700 Subject: [PATCH 2/5] rustdoc cleanup: remove unused function --- src/librustdoc/html/static/css/themes/ayu.css | 2 +- src/librustdoc/html/static/css/themes/dark.css | 2 +- src/librustdoc/html/static/css/themes/light.css | 3 +-- src/librustdoc/html/static/js/source-script.js | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index a78ac5da7490b..63f64dc69e893 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -635,7 +635,7 @@ kbd { background-color: #14191f; color: #ffb44c; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #14191f; color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index a2abd53fa02bc..d1f79b5b08219 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -504,7 +504,7 @@ kbd { #source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #444; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #333; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index c4510ad6ae66b..e09b1f7a5e2e4 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -488,10 +488,9 @@ kbd { #source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #E0E0E0; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #fff; } - .scraped-example-list .scrape-help { border-color: #555; color: #333; diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 21c3609279075..9173e93e7c804 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -2,7 +2,7 @@ /* global sourcesIndex */ // Local js definitions: -/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, browserSupportsHistoryApi */ +/* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ /* global updateLocalStorage */ "use strict"; From 180f83605afbd8abe58e79df475df0e0958401b3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 1 Jul 2022 15:29:47 -0700 Subject: [PATCH 3/5] rustdoc: add spacing to the source view sidebar https://user-images.githubusercontent.com/1593513/176974336-20cecdc3-1885-402a-a6d5-81a8dd03a45d.png --- src/librustdoc/html/static/css/rustdoc.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 7d5318a194c7d..4e9b75eba6a4e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1528,6 +1528,10 @@ kbd { margin-bottom: 1em; } +details.dir-entry { + padding-left: 4px; +} + details.dir-entry > summary { margin: 0 0 0 13px; list-style-position: outside; @@ -1535,7 +1539,7 @@ details.dir-entry > summary { } details.dir-entry div.folders, details.dir-entry div.files { - padding-left: 27px; + padding-left: 23px; } details.dir-entry a { From b80979416d3eb7aa55c3f01b107f17f0363bf92e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 1 Jul 2022 16:16:03 -0700 Subject: [PATCH 4/5] rustdoc: add test cases for :focus on sidebar details elements --- .../sidebar-source-code-display.goml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index 1d8cc22100c3d..edcd98dfd937f 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -35,6 +35,13 @@ assert-css: ( "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( @@ -46,6 +53,13 @@ assert-css: ( "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( @@ -67,6 +81,13 @@ assert-css: ( "#source-sidebar details[open] > .files > a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( @@ -78,6 +99,13 @@ assert-css: ( "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( @@ -99,6 +127,13 @@ assert-css: ( "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( @@ -110,6 +145,13 @@ assert-css: ( "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( From e710ac12fac9d650fb53b27259332cabdc9416f5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 2 Jul 2022 09:42:49 -0700 Subject: [PATCH 5/5] rustdoc: add test case for source sidebar spacing --- src/test/rustdoc-gui/source-code-page.goml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 05b0e809bca69..581f826a3d94d 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -44,3 +44,6 @@ assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) // And now we collapse it again. click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) + +// Check the spacing. +assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"})