From 0d6d23925df8800f4ab0f8e1d3eac1401fb64a6f Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 8 May 2024 12:42:47 -0300 Subject: content, client, css: misc search frontend additions --- src/content/dependencies/generatePageSidebar.js | 3 +- .../dependencies/generateSearchSidebarBox.js | 3 + src/static/css/site.css | 114 +++++++++++++++------ src/static/js/client.js | 69 ++++++++++++- src/static/js/search-worker.js | 1 + src/strings-default.yaml | 1 + 6 files changed, 154 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/content/dependencies/generatePageSidebar.js b/src/content/dependencies/generatePageSidebar.js index 43015aa3..3ec928db 100644 --- a/src/content/dependencies/generatePageSidebar.js +++ b/src/content/dependencies/generatePageSidebar.js @@ -19,14 +19,13 @@ export default { // Sticky mode controls which sidebar sections, if any, follow the // scroll position, "sticking" to the top of the browser viewport. // - // 'last' - last or only sidebar box is sticky // 'column' - entire column, incl. multiple boxes from top, is sticky // 'static' - sidebar not sticky at all, stays at top of page // // Note: This doesn't affect the content of any sidebar section, only // the whole section's containing box (or the sidebar column as a whole). stickyMode: { - validate: v => v.is('last', 'column', 'static'), + validate: v => v.is('column', 'static'), default: 'static', }, diff --git a/src/content/dependencies/generateSearchSidebarBox.js b/src/content/dependencies/generateSearchSidebarBox.js index 7dd0b3c8..c534c492 100644 --- a/src/content/dependencies/generateSearchSidebarBox.js +++ b/src/content/dependencies/generateSearchSidebarBox.js @@ -25,6 +25,9 @@ export default { html.tag('template', {class: 'wiki-search-current-result-string'}, language.$('misc.search.currentResult')), + + html.tag('template', {class: 'wiki-search-end-search-string'}, + language.$('misc.search.endSearch')), ], }), }; diff --git a/src/static/css/site.css b/src/static/css/site.css index c8fe9cde..c7267b2f 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -463,16 +463,15 @@ summary .group-name { } .wiki-search-sidebar-box { - padding: 2px; - position: sticky; - top: 5px; + padding: 1px 0 0 0; + z-index: 999; + max-height: calc(100vh - 20px); + + display: flex; + flex-direction: column; background-color: #000000c0; - box-shadow: - 0 3px 4px #00000080, - 0 -2px 8px #000000c0, - 0 -6px 3px #000000f0; -webkit-backdrop-filter: brightness(1.2) blur(4px); @@ -481,22 +480,51 @@ summary .group-name { brightness(1.2) blur(4px); } +.wiki-search-sidebar-box.showing-results { + position: sticky; + top: 5px; + + box-shadow: + 0 4px 16px -8px var(--primary-color), + 0 10px 6px var(--bg-black-color), + 0 6px 4px #00000040; +} + +.wiki-search-sidebar-box.showing-results ~ .sidebar:not(:hover) { + opacity: 0.6; + filter: brightness(0.5); +} + .wiki-search-input { - width: 100%; + width: calc(100% - 4px); + padding: 2px 4px; + margin: 2px 2px 3px 2px; + box-sizing: border-box; + background: transparent; border: 1px solid var(--dim-color); border-radius: 3px; - padding: 2px 4px; color: inherit; } -.wiki-search-results-container hr { +.wiki-search-sidebar-box hr { border-color: var(--primary-color); border-style: none none dotted none; } +.wiki-search-sidebar-box hr:nth-of-type(1) { + margin-top: 3px; + margin-bottom: 6px; +} + +.wiki-search-sidebar-box hr:nth-of-type(2) { + margin-top: 6px; + margin-bottom: 0; +} + .wiki-search-results-container { - margin-bottom: 5px; + margin-bottom: 0; + padding: 2px; } .wiki-search-no-results { @@ -523,7 +551,7 @@ summary .group-name { left: 0; right: 0; - border: 2px solid var(--primary-color); + border: 1.5px solid var(--primary-color); border-radius: 4px; display: none; } @@ -560,6 +588,7 @@ summary .group-name { height: 1.8em; margin-right: 6px; border-radius: 2px; + aspect-ratio: 1 / 1; } .wiki-search-result-image-placeholder { @@ -570,8 +599,29 @@ summary .group-name { display: none; } +.wiki-search-end-search-line { + text-align: center; + margin-top: 6px; + margin-bottom: 2px; +} + +.wiki-search-end-search-line a { + display: inline-block; + font-style: oblique; + opacity: 0.9; + padding: 3px 6px 4px 6px; + border-radius: 4px; + border: 1.5px solid transparent; +} + +.wiki-search-end-search-line a:hover { + opacity: 1; + background: var(--light-ghost-color); + border-color: var(--deep-color); +} + .wiki-search-input:focus { - border: 1px solid var(--primary-color); + border-color: var(--primary-color); } .wiki-search-input::placeholder { @@ -2206,40 +2256,40 @@ main.long-content .content-sticky-heading-container .content-sticky-subheading-r /* Sticky sidebar */ -.sidebar-column.sidebar.sticky-column, -.sidebar-column.sidebar.sticky-last, -.sidebar-multiple.sticky-last > .sidebar:last-child, -.sidebar-multiple.sticky-column { - position: sticky; - top: 10px; -} - -.sidebar-multiple.sticky-last { +.sidebar-column:not(.sticky-column) { align-self: stretch; } -.sidebar-multiple.sticky-column { +.sidebar-column.sticky-column { + position: sticky; + top: 10px; align-self: flex-start; + max-height: calc(100vh - 20px); + display: flex; + flex-direction: column; } -.sidebar-column.sidebar.sticky-column { - max-height: calc(100vh - 20px); - align-self: start; - padding-bottom: 0; - box-sizing: border-box; - flex-basis: 275px; - padding-top: 0; +.sidebar-multiple.sticky-column .sidebar:last-child { + flex-shrink: 1; + overflow-y: scroll; + scrollbar-width: thin; + scrollbar-color: var(--dark-color); +} + +.wiki-search-sidebar-box .wiki-search-results-container { overflow-y: scroll; scrollbar-width: thin; scrollbar-color: var(--dark-color); } -.sidebar-column.sidebar.sticky-column::-webkit-scrollbar { +.sidebar-column.sticky-column .sidebar:last-child::-webkit-scrollbar, +.wiki-search-sidebar-box .wiki-search-results-container::-webkit-scrollbar { background: var(--dark-color); width: 12px; } -.sidebar-column.sidebar.sticky-column::-webkit-scrollbar-thumb { +.sidebar-column.sticky-column .sidebar:last-child::-webkit-scrollbar-thumb, +.wiki-search-sidebar-box .wiki-search-results-container::-webkit-scrollbar-thumb { transition: background 0.2s; background: rgba(255, 255, 255, 0.2); border: 3px solid transparent; diff --git a/src/static/js/client.js b/src/static/js/client.js index 46d66bcc..97a046e5 100644 --- a/src/static/js/client.js +++ b/src/static/js/client.js @@ -3576,11 +3576,17 @@ const sidebarSearchInfo = initInfo('sidebarSearchInfo', { searchBox: null, searchInput: null, + resultsRule: null, resultsContainer: null, results: null, + endSearchRule: null, + endSearchLine: null, + endSearchLink: null, + noResultsString: null, currentResultString: null, + endSearchString: null, state: { stoppedTypingTimeout: null, @@ -3609,11 +3615,17 @@ function getSidebarSearchReferences() { info.searchInput = info.searchBox.querySelector('.wiki-search-input'); + const findString = classPart => + info.searchBox.querySelector(`.wiki-search-${classPart}-string`); + info.noResultsString = - info.searchBox.querySelector('.wiki-search-no-results-string'); + findString('no-results'); info.currentResultString = - info.searchBox.querySelector('.wiki-search-current-result-string'); + findString('current-result'); + + info.endSearchString = + findString('end-search'); } function mutateSidebarSearchContent() { @@ -3621,13 +3633,16 @@ function mutateSidebarSearchContent() { if (!info.searchBox) return; + info.resultsRule = + document.createElement('hr'); + info.resultsContainer = document.createElement('div'); info.resultsContainer.classList.add('wiki-search-results-container'); + cssProp(info.resultsRule, 'display', 'none'); cssProp(info.resultsContainer, 'display', 'none'); - info.resultsContainer.appendChild(document.createElement('hr')); info.results = document.createElement('div'); @@ -3636,7 +3651,34 @@ function mutateSidebarSearchContent() { info.resultsContainer.appendChild(info.results); + info.searchBox.appendChild(info.resultsRule); info.searchBox.appendChild(info.resultsContainer); + + info.endSearchRule = + document.createElement('hr'); + + info.searchBox.appendChild(info.endSearchRule); + + info.endSearchLine = + document.createElement('p'); + + info.endSearchLink = + document.createElement('a'); + + { + const p = info.endSearchLine; + const a = info.endSearchLink; + p.classList.add('wiki-search-end-search-line'); + a.setAttribute('href', '#'); + a.appendChild(templateContent(info.endSearchString)); + p.appendChild(a); + } + + cssProp(info.endSearchRule, 'display', 'none'); + cssProp(info.endSearchLine, 'display', 'none'); + + info.searchBox.appendChild(info.endSearchRule); + info.searchBox.appendChild(info.endSearchLine); } function addSidebarSearchListeners() { @@ -3667,6 +3709,11 @@ function addSidebarSearchListeners() { activateSidebarSearch(info.searchInput.value); }, settings.stoppedTyingDelay); }); + + info.endSearchLink.addEventListener('click', domEvent => { + domEvent.preventDefault(); + clearSidebarSearch(); + }); } function initializeSidebarSearchState() { @@ -3715,8 +3762,12 @@ function clearSidebarSearch() { state.stoppedTypingTimeout = null; } + info.searchBox.classList.remove('showing-results'); + info.searchInput.value = ''; + session.activeQuery = ''; + session.activeQueryResults = ''; hideSidebarSearchResults(); } @@ -3738,10 +3789,13 @@ function showSidebarSearchResults(results) { data: doc, }))); + info.searchBox.classList.add('showing-results'); + while (info.results.firstChild) { info.results.firstChild.remove(); } + cssProp(info.resultsRule, 'display', 'block'); cssProp(info.resultsContainer, 'display', 'block'); if (empty(flatResults)) { @@ -3757,6 +3811,11 @@ function showSidebarSearchResults(results) { info.results.appendChild(el); } + + if (!empty(flatResults)) { + cssProp(info.endSearchRule, 'display', 'block'); + cssProp(info.endSearchLine, 'display', 'block'); + } } function generateSidebarSearchResult(result) { @@ -3883,11 +3942,15 @@ function generateSidebarSearchResultTemplate(slots) { function hideSidebarSearchResults() { const info = sidebarSearchInfo; + cssProp(info.resultsRule, 'display', 'none'); cssProp(info.resultsContainer, 'display', 'none'); while (info.results.firstChild) { info.results.firstChild.remove(); } + + cssProp(info.endSearchRule, 'display', 'none'); + cssProp(info.endSearchLine, 'display', 'none'); } clientSteps.getPageReferences.push(getSidebarSearchReferences); diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js index e61b3c30..a6ecd3ab 100644 --- a/src/static/js/search-worker.js +++ b/src/static/js/search-worker.js @@ -120,6 +120,7 @@ function queryGenericIndex(index, query, options) { const interestingFieldCombinations = [ ['primaryName', 'contributors', 'groups'], ['primaryName', 'groups'], + ['contributors', 'groups'], ['primaryName', 'contributors'], ['primaryName'], ]; diff --git a/src/strings-default.yaml b/src/strings-default.yaml index 47e96a97..8486fa6a 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -627,6 +627,7 @@ misc: Check spelling and use complete words. currentResult: "(you are here)" + endSearch: "(OK, I'm done searching now.)" # skippers: # -- cgit 1.3.0-6-gf8a5