From d3c3e25674fb132a1c905117e829b016a7d0c3cd Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 9 Sep 2025 14:23:28 -0700 Subject: [PATCH 1/5] rustdoc-search: remove animated throbber Complaints about it being distracting, and causing people to wait until all of the results are loaded instead of using the incremental results as they come in, make me think this is a bad idea. --- src/librustdoc/html/static/css/rustdoc.css | 64 ---------------------- 1 file changed, 64 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 09d289d570c06..a0b3b2de3dbf4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1987,12 +1987,10 @@ a.tooltip:hover::after { color: inherit; } #search-tabs button:not(.selected) { - --search-tab-button-background: var(--search-tab-button-not-selected-background); background-color: var(--search-tab-button-not-selected-background); border-top-color: var(--search-tab-button-not-selected-border-top-color); } #search-tabs button:hover, #search-tabs button.selected { - --search-tab-button-background: var(--search-tab-button-selected-background); background-color: var(--search-tab-button-selected-background); border-top-color: var(--search-tab-button-selected-border-top-color); } @@ -2008,68 +2006,6 @@ a.tooltip:hover::after { color: transparent; } -.search-form.loading { - --search-tab-button-background: var(--button-background-color); -} - -#search-tabs .count.loading::before, -.search-form.loading::before -{ - width: 16px; - height: 16px; - border-radius: 16px; - background: radial-gradient( - var(--search-tab-button-background) 0 50%, - transparent 50% 100% - ), conic-gradient( - var(--code-highlight-kw-color) 0deg 30deg, - var(--code-highlight-prelude-color) 30deg 60deg, - var(--code-highlight-number-color) 90deg 120deg, - var(--code-highlight-lifetime-color ) 120deg 150deg, - var(--code-highlight-comment-color) 150deg 180deg, - var(--code-highlight-self-color) 180deg 210deg, - var(--code-highlight-attribute-color) 210deg 240deg, - var(--code-highlight-literal-color) 210deg 240deg, - var(--code-highlight-macro-color) 240deg 270deg, - var(--code-highlight-question-mark-color) 270deg 300deg, - var(--code-highlight-prelude-val-color) 300deg 330deg, - var(--code-highlight-doc-comment-color) 330deg 360deg - ); - content: ""; - position: absolute; - left: 2px; - top: 2px; - animation: rotating 1.25s linear infinite; -} -#search-tabs .count.loading::after, -.search-form.loading::after -{ - width: 18px; - height: 18px; - border-radius: 18px; - background: conic-gradient( - var(--search-tab-button-background) 0deg 180deg, - transparent 270deg 360deg - ); - content: ""; - position: absolute; - left: 1px; - top: 1px; - animation: rotating 0.66s linear infinite; -} - -.search-form.loading::before { - left: auto; - right: 9px; - top: 8px; -} - -.search-form.loading::after { - left: auto; - right: 8px; - top: 8px; -} - #search .error code { border-radius: 3px; background-color: var(--search-error-code-background-color); From 2773d24fb701cb17d587289cf75725b5d9bcd328 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 10 Sep 2025 11:23:40 -0700 Subject: [PATCH 2/5] rustdoc-search: put throbber at bottom of search results instead --- src/librustdoc/html/static/css/rustdoc.css | 52 ++++++++++++++++++++++ src/librustdoc/html/static/js/search.js | 19 ++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a0b3b2de3dbf4..d86dc66ab01be 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -339,6 +339,7 @@ summary.hideme, .scraped-example-list, .rustdoc-breadcrumbs, .search-switcher, +.search-throbber, /* This selector is for the items listed in the "all items" page. */ ul.all-items { font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; @@ -2006,6 +2007,57 @@ a.tooltip:hover::after { color: transparent; } +.search-throbber { + position: relative; + height: 34px; +} + +.search-throbber::before, +.search-form.loading::before +{ + width: 16px; + height: 16px; + border-radius: 16px; + background: radial-gradient( + var(--button-background-color) 0 50%, + transparent 50% 100% + ), conic-gradient( + var(--code-highlight-kw-color) 0deg 30deg, + var(--code-highlight-prelude-color) 30deg 60deg, + var(--code-highlight-number-color) 90deg 120deg, + var(--code-highlight-lifetime-color ) 120deg 150deg, + var(--code-highlight-comment-color) 150deg 180deg, + var(--code-highlight-self-color) 180deg 210deg, + var(--code-highlight-attribute-color) 210deg 240deg, + var(--code-highlight-literal-color) 210deg 240deg, + var(--code-highlight-macro-color) 240deg 270deg, + var(--code-highlight-question-mark-color) 270deg 300deg, + var(--code-highlight-prelude-val-color) 300deg 330deg, + var(--code-highlight-doc-comment-color) 330deg 360deg + ); + content: ""; + position: absolute; + right: 9px; + top: 8px; + animation: rotating 1.25s linear infinite; +} +.search-throbber::after, +.search-form.loading::after +{ + width: 18px; + height: 18px; + border-radius: 18px; + background: conic-gradient( + var(--button-background-color) 0deg 180deg, + transparent 270deg 360deg + ); + content: ""; + position: absolute; + right: 8px; + top: 8px; + animation: rotating 0.66s linear infinite; +} + #search .error code { border-radius: 3px; background-color: var(--search-error-code-background-color); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 9a6d4c710ff5d..ba8363b1a9147 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -4904,6 +4904,11 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) { let output = document.createElement("ul"); output.className = "search-results " + extraClass; + const throbber = document.createElement("div"); + throbber.className = "search-throbber"; + throbber.innerHTML = "Loading..."; + output.appendChild(throbber); + let count = 0; /** @type {Promise[]} */ @@ -5010,7 +5015,7 @@ ${obj.displayPath}${name}\ } link.appendChild(description); - output.appendChild(link); + output.insertBefore(link, throbber); results.next().then(async nextResult => { if (nextResult.value) { @@ -5019,7 +5024,10 @@ ${obj.displayPath}${name}\ await Promise.all(descList); // need to make sure the element is shown before // running this callback - yieldToBrowser().then(() => finishedCallback(count, output)); + yieldToBrowser().then(() => { + finishedCallback(count, output); + throbber.remove(); + }); } }); }; @@ -5215,9 +5223,14 @@ async function showResults(docSearch, results, goToFirst, filterCrates) { resultsElem.id = "results"; search.innerHTML = ""; - for (const [tab, output] of tabs) { + for (const [tabNb, [tab, output]] of tabs.entries()) { tabsElem.appendChild(tab); + const isCurrentTab = window.searchState.currentTab === tabNb; const placeholder = document.createElement("div"); + placeholder.className = isCurrentTab ? + "search-throbber search-results active" : + "search-throbber search-results"; + placeholder.innerHTML = "Loading..."; output.then(output => { if (placeholder.parentElement) { placeholder.parentElement.replaceChild(output, placeholder); From 5c31880034def5ce8fc22ded984a875fa39965d3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 6 Oct 2025 10:43:37 -0700 Subject: [PATCH 3/5] rustdoc-search: use a throbbler with no motion This change is a response to complaints about motion sickness. --- src/librustdoc/html/static/css/rustdoc.css | 48 ++++++---------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d86dc66ab01be..8078f87756dd2 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2012,50 +2012,28 @@ a.tooltip:hover::after { height: 34px; } -.search-throbber::before, -.search-form.loading::before -{ - width: 16px; - height: 16px; - border-radius: 16px; - background: radial-gradient( - var(--button-background-color) 0 50%, - transparent 50% 100% - ), conic-gradient( - var(--code-highlight-kw-color) 0deg 30deg, - var(--code-highlight-prelude-color) 30deg 60deg, - var(--code-highlight-number-color) 90deg 120deg, - var(--code-highlight-lifetime-color ) 120deg 150deg, - var(--code-highlight-comment-color) 150deg 180deg, - var(--code-highlight-self-color) 180deg 210deg, - var(--code-highlight-attribute-color) 210deg 240deg, - var(--code-highlight-literal-color) 210deg 240deg, - var(--code-highlight-macro-color) 240deg 270deg, - var(--code-highlight-question-mark-color) 270deg 300deg, - var(--code-highlight-prelude-val-color) 300deg 330deg, - var(--code-highlight-doc-comment-color) 330deg 360deg - ); - content: ""; - position: absolute; - right: 9px; - top: 8px; - animation: rotating 1.25s linear infinite; -} .search-throbber::after, .search-form.loading::after { width: 18px; height: 18px; border-radius: 18px; - background: conic-gradient( - var(--button-background-color) 0deg 180deg, - transparent 270deg 360deg - ); - content: ""; + /* hourglass */ + content: url('data:image/svg+xml,\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + '); position: absolute; right: 8px; top: 8px; - animation: rotating 0.66s linear infinite; + filter: var(--settings-menu-filter); } #search .error code { From 6d4b4d9ef080bd2fb2fe0cd81789998ff6064167 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Oct 2025 11:17:44 -0700 Subject: [PATCH 4/5] rustdoc-search: keep hourglass in searchbar --- src/librustdoc/html/static/css/rustdoc.css | 7 ------ src/librustdoc/html/static/js/search.js | 29 ++++++++++------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8078f87756dd2..7f47856948493 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -339,7 +339,6 @@ summary.hideme, .scraped-example-list, .rustdoc-breadcrumbs, .search-switcher, -.search-throbber, /* This selector is for the items listed in the "all items" page. */ ul.all-items { font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; @@ -2007,12 +2006,6 @@ a.tooltip:hover::after { color: transparent; } -.search-throbber { - position: relative; - height: 34px; -} - -.search-throbber::after, .search-form.loading::after { width: 18px; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index ba8363b1a9147..0929d351463cc 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getVar, nonnull, getSettingValue */ +/* global addClass, getNakedUrl, getVar, getSettingValue, hasClass, nonnull */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi */ "use strict"; @@ -4804,6 +4804,15 @@ function printTab(nb) { if (nb === iter) { addClass(elem, "selected"); foundCurrentTab = true; + onEachLazy(document.querySelectorAll( + ".search-form", + ), form => { + if (hasClass(elem.firstElementChild, "loading")) { + addClass(form, "loading"); + } else { + removeClass(form, "loading"); + } + }); } else { removeClass(elem, "selected"); } @@ -4904,11 +4913,6 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) { let output = document.createElement("ul"); output.className = "search-results " + extraClass; - const throbber = document.createElement("div"); - throbber.className = "search-throbber"; - throbber.innerHTML = "Loading..."; - output.appendChild(throbber); - let count = 0; /** @type {Promise[]} */ @@ -5015,7 +5019,7 @@ ${obj.displayPath}${name}\ } link.appendChild(description); - output.insertBefore(link, throbber); + output.appendChild(link); results.next().then(async nextResult => { if (nextResult.value) { @@ -5026,7 +5030,6 @@ ${obj.displayPath}${name}\ // running this callback yieldToBrowser().then(() => { finishedCallback(count, output); - throbber.remove(); }); } }); @@ -5164,6 +5167,7 @@ function makeTab(tabNb, text, results, query, isTypeSearch, goToFirst) { count < 100 ? `\u{2007}(${count})\u{2007}` : `\u{2007}(${count})`; tabCount.innerHTML = fmtNbElems; tabCount.className = "count"; + printTab(window.searchState.currentTab); }, isTypeSearch), ]; } @@ -5227,9 +5231,7 @@ async function showResults(docSearch, results, goToFirst, filterCrates) { tabsElem.appendChild(tab); const isCurrentTab = window.searchState.currentTab === tabNb; const placeholder = document.createElement("div"); - placeholder.className = isCurrentTab ? - "search-throbber search-results active" : - "search-throbber search-results"; + placeholder.className = isCurrentTab ? "search-results active" : "search-results"; placeholder.innerHTML = "Loading..."; output.then(output => { if (placeholder.parentElement) { @@ -5487,11 +5489,6 @@ if (ROOT_PATH === null) { const database = await Stringdex.loadDatabase(hooks); if (typeof window !== "undefined") { docSearch = new DocSearch(ROOT_PATH, database); - onEachLazy(document.querySelectorAll( - ".search-form.loading", - ), form => { - removeClass(form, "loading"); - }); registerSearchEvents(); // If there's a search term in the URL, execute the search now. if (window.searchState.getQueryStringParams().search !== undefined) { From c9293bfdae35a9975dca633435ed1b17bbacbf87 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Oct 2025 12:59:58 -0700 Subject: [PATCH 5/5] rustdoc-search: add test case for throbber --- tests/rustdoc-gui/search-throbber.goml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/rustdoc-gui/search-throbber.goml diff --git a/tests/rustdoc-gui/search-throbber.goml b/tests/rustdoc-gui/search-throbber.goml new file mode 100644 index 0000000000000..9d41f933af8c1 --- /dev/null +++ b/tests/rustdoc-gui/search-throbber.goml @@ -0,0 +1,23 @@ +// We are intentionally triggering errors for race-free throbber test +fail-on-request-error: false +fail-on-js-error: false + +// First, make sure the throbber goes away when done +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=" +wait-for: ".search-input" +wait-for-false: ".search-form.loading" +write-into: (".search-input", "test") +press-key: 'Enter' +wait-for-false: ".search-form.loading" + +// Make sure the throbber shows up if we prevent the search from +// ever finishing (this tactic is needed to make sure we don't get stuck +// with any race conditions). +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=" +block-network-request: "*/desc/*.js" +reload: +wait-for: ".search-input" +wait-for-false: ".search-form.loading" +write-into: (".search-input", "test") +press-key: 'Enter' +wait-for: ".search-form.loading"