From 2fcee013120942363e0a8bea8fef964a8a62e6ea Mon Sep 17 00:00:00 2001 From: Anjo Vahldiek-Oberwagner Date: Mon, 18 May 2026 15:50:31 +0200 Subject: [PATCH] feat: compact search page with justified tagline, persistent toolbar & unified results Redesign the search/index page for a cleaner, more stable layout: - Shared hero CSS (reprodb-search-hero.css) used by both search and profile pages - Justified tagline text with ReproDB branding; fades out on search - Persistent toolbar: filters, sort dropdown, result count, download & share buttons all in one row that never moves or hides - Result count includes both artifact results and profile cards - Default page size reduced from 50 to 20 - Scrollbar always visible to prevent horizontal layout shift - Dark mode support throughout --- src/_includes/profile_common.html | 1 + src/assets/css/reprodb-profile.css | 49 +--------- src/assets/css/reprodb-search-hero.css | 108 +++++++++++++++++++++ src/assets/css/reprodb-search.css | 126 ++++++++----------------- src/assets/js/reprodb-search.js | 63 ++++++++----- src/assets/js/reprodb-utils.js | 2 +- src/index.md | 76 ++++++++------- src/profile.md | 10 +- 8 files changed, 242 insertions(+), 193 deletions(-) create mode 100644 src/assets/css/reprodb-search-hero.css diff --git a/src/_includes/profile_common.html b/src/_includes/profile_common.html index 1f714f99..89ba18f3 100644 --- a/src/_includes/profile_common.html +++ b/src/_includes/profile_common.html @@ -3,5 +3,6 @@ Provides: search/autocomplete, share button, URL bar management, utility functions. Usage: include profile_common.html (with liquid curly-percent tags) --> + diff --git a/src/assets/css/reprodb-profile.css b/src/assets/css/reprodb-profile.css index edaaf338..dba72b28 100644 --- a/src/assets/css/reprodb-profile.css +++ b/src/assets/css/reprodb-profile.css @@ -1,14 +1,9 @@ -/* reprodb-profile.css — Styles for the unified profile page and profile_common. */ +/* reprodb-profile.css — Styles for the unified profile page and profile_common. + Search box & hero base styles are in reprodb-search-hero.css (shared). */ -/* ── Search hero container ─────────────────────────────────────────────── */ +/* ── Profile-specific hero overrides ───────────────────────────────────── */ .profile-search-hero { - display: flex; - align-items: center; - justify-content: center; min-height: 40vh; - text-align: center; - transition: min-height 0.4s ease, padding 0.4s ease; - padding: 0 16px; } .profile-search-hero.has-profile { min-height: 0; @@ -16,9 +11,7 @@ padding-bottom: 0; } .profile-search-hero-inner { - width: 100%; max-width: 600px; - transition: max-width 0.4s ease; } .profile-search-hero.has-profile .profile-search-hero-inner { max-width: 480px; @@ -26,7 +19,6 @@ .profile-search-heading { font-size: 1.4em; font-weight: 400; - color: #555; margin-bottom: 16px; transition: font-size 0.4s ease, margin 0.4s ease, opacity 0.3s ease; } @@ -38,31 +30,6 @@ height: 0; } -/* ── Search box ────────────────────────────────────────────────────────── */ -.profile-search-box { - display: block; - width: 100%; - padding: 14px 48px 14px 20px; - font-size: 1.1em; - border: 2px solid #ddd; - border-radius: 28px; - outline: none; - box-shadow: 0 2px 8px rgba(0,0,0,0.08); - transition: box-shadow 0.2s, border-color 0.2s; - box-sizing: border-box; -} -.profile-search-box:focus { - box-shadow: 0 4px 16px rgba(0,0,0,0.12); - border-color: #4285f4; -} -.profile-search-icon { - position: absolute; - right: 16px; - top: 50%; - transform: translateY(-50%); - pointer-events: none; -} - /* ── Autocomplete results ──────────────────────────────────────────────── */ .profile-search-results { list-style:none; padding:0; margin:4px 0 0 0; max-height:260px; overflow-y:auto; border:1px solid #ddd; border-radius:12px; position:absolute; background:#fff; z-index:100; width:100%; box-shadow: 0 4px 16px rgba(0,0,0,0.10); } .profile-search-results li { padding:8px 14px; cursor:pointer; border-bottom:1px solid #f0f0f0; } @@ -159,11 +126,6 @@ /* ── Dark-mode overrides ───────────────────────────────────────────────── */ @media (prefers-color-scheme: dark) { html:not([data-theme="light"]) .profile-search-heading { color: #aab0b8; } - html:not([data-theme="light"]) .profile-search-box { - background-color: #1e2127; color: #d6d9dc; border-color: #4a4f57; - } - html:not([data-theme="light"]) .profile-search-box:focus { border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } - html:not([data-theme="light"]) .profile-search-icon { stroke: #888; } html:not([data-theme="light"]) .profile-search-results { background: #1e2127; border-color: #4a4f57; color: #d6d9dc; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } @@ -192,11 +154,6 @@ html:not([data-theme="light"]) .avail-warn { color: #f0c040; background: #332b00; border-color: #665500; } } html[data-theme="dark"] .profile-search-heading { color: #aab0b8; } -html[data-theme="dark"] .profile-search-box { - background-color: #1e2127; color: #d6d9dc; border-color: #4a4f57; -} -html[data-theme="dark"] .profile-search-box:focus { border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } -html[data-theme="dark"] .profile-search-icon { stroke: #888; } html[data-theme="dark"] .profile-search-results { background: #1e2127; border-color: #4a4f57; color: #d6d9dc; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } diff --git a/src/assets/css/reprodb-search-hero.css b/src/assets/css/reprodb-search-hero.css new file mode 100644 index 00000000..4e377da5 --- /dev/null +++ b/src/assets/css/reprodb-search-hero.css @@ -0,0 +1,108 @@ +/* reprodb-search-hero.css — Shared search hero styles for index and profile pages. + Provides the collapsible hero container, search box, and search icon. */ + +/* ── Hero container ────────────────────────────────────────────────────── */ +.rdb-search-hero { + display: flex; + align-items: center; + justify-content: center; + min-height: 30vh; + transition: min-height 0.4s ease, padding 0.4s ease; + padding: 0 16px; +} +.rdb-search-hero.has-results { + min-height: 0; + padding-top: 8px; + padding-bottom: 0; +} +.rdb-search-hero-inner { + width: 100%; + max-width: 720px; + transition: max-width 0.4s ease; +} +.rdb-search-hero.has-results .rdb-search-hero-inner { + max-width: 720px; +} + +/* ── Tagline / heading that fades out ──────────────────────────────────── */ +.rdb-search-tagline { + font-size: 0.92em; + color: #555; + margin-bottom: 16px; + line-height: 1.6; + text-align: justify; + transition: font-size 0.35s ease, margin 0.35s ease, opacity 0.3s ease, + max-height 0.35s ease, padding 0.35s ease; + max-height: 8em; + overflow: hidden; +} +@media (max-width: 600px) { + .rdb-search-tagline { font-size: 0.88em; } +} +.rdb-search-hero.has-results .rdb-search-tagline { + font-size: 0; + margin: 0; + opacity: 0; + max-height: 0; + padding: 0; +} + +/* ── Search box (shared between profile and artifact search) ───────────── */ +.rdb-search-box-wrap { + position: relative; + width: 100%; +} +.rdb-search-input { + display: block; + width: 100%; + padding: 14px 48px 14px 20px; + font-size: 1.1em; + border: 2px solid #ddd; + border-radius: 28px; + outline: none; + box-shadow: 0 2px 8px rgba(0,0,0,0.08); + transition: box-shadow 0.2s, border-color 0.2s; + box-sizing: border-box; + background: #fff; + color: #333; +} +.rdb-search-input:focus { + box-shadow: 0 4px 16px rgba(0,0,0,0.12); + border-color: #4285f4; +} +.rdb-search-icon { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + pointer-events: none; +} +.rdb-search-clear { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + cursor: pointer; +} + +/* ── Dark-mode ─────────────────────────────────────────────────────────── */ +@media (prefers-color-scheme: dark) { + html:not([data-theme="light"]) .rdb-search-tagline { color: #aab0b8; } + html:not([data-theme="light"]) .rdb-search-input { + background: #1e2127; color: #d6d9dc; border-color: #4a4f57; + } + html:not([data-theme="light"]) .rdb-search-input:focus { + border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); + } + html:not([data-theme="light"]) .rdb-search-icon { stroke: #888; } + html:not([data-theme="light"]) .rdb-search-clear { stroke: #888; } +} +html[data-theme="dark"] .rdb-search-tagline { color: #aab0b8; } +html[data-theme="dark"] .rdb-search-input { + background: #1e2127; color: #d6d9dc; border-color: #4a4f57; +} +html[data-theme="dark"] .rdb-search-input:focus { + border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); +} +html[data-theme="dark"] .rdb-search-icon { stroke: #888; } +html[data-theme="dark"] .rdb-search-clear { stroke: #888; } diff --git a/src/assets/css/reprodb-search.css b/src/assets/css/reprodb-search.css index 7d7f8f53..ba4766db 100644 --- a/src/assets/css/reprodb-search.css +++ b/src/assets/css/reprodb-search.css @@ -1,105 +1,65 @@ -/* reprodb-search.css — Styles for the main search / index page. */ +/* reprodb-search.css — Styles for the main search / index page. + Search box & hero styles are in reprodb-search-hero.css (shared). */ /* ── Search container ──────────────────────────────────────────────────── */ +html { overflow-y: scroll; } #search-container { - max-width: 720px; - margin: 2em auto; - text-align: center; -} -.rdb-search-box-wrap { - position: relative; - width: 100%; -} -#searchBox { - display: block; width: 100%; - padding: 14px 48px 14px 20px; - font-size: 1.1em; - border: 2px solid #ddd; - border-radius: 28px; - outline: none; - box-shadow: 0 2px 8px rgba(0,0,0,0.08); - transition: box-shadow 0.2s, border-color 0.2s; - box-sizing: border-box; - background: #fff; - color: #333; -} -#searchBox:focus { - box-shadow: 0 4px 16px rgba(0,0,0,0.12); - border-color: #4285f4; -} -.rdb-search-icon { - position: absolute; - right: 16px; - top: 50%; - transform: translateY(-50%); - pointer-events: none; -} -#clearIcon { - position: absolute; - right: 16px; - top: 50%; - transform: translateY(-50%); - cursor: pointer; } -/* ── Filters row ───────────────────────────────────────────────────────── */ +/* ── Filters / toolbar row ─────────────────────────────────────────── */ #filters { - margin-top: 12px; + margin-top: 10px; display: flex; flex-wrap: wrap; - gap: 10px; - justify-content: center; + gap: 8px; align-items: center; } #filters select { - padding: 8px 12px; + padding: 6px 10px; border: 1px solid #ccc; border-radius: 6px; - font-size: 0.95em; + font-size: 0.9em; background: #fff; } -.rdb-area-checks { +.rdb-search-status { + margin-left: auto; + font-size: 0.85em; + color: #666; + white-space: nowrap; +} +#sortSelect { + font-size: 0.85em; +} + +/* ── Icon action buttons ──────────────────────────────────────────── */ +.rdb-action-btns { display: inline-flex; - gap: 10px; + gap: 2px; align-items: center; } -.rdb-area-checks label { +.rdb-icon-btn { display: inline-flex; align-items: center; - gap: 4px; - font-size: 0.95em; - cursor: pointer; - user-select: none; -} - -/* ── Status & action buttons ───────────────────────────────────────────── */ -#searchStatus { - margin-top: 8px; - font-size: 0.9em; - color: #666; - display: inline; -} -.rdb-search-action-btn { - margin-left: 10px; - padding: 4px 14px; + justify-content: center; + width: 28px; + height: 28px; + padding: 0; border: 1px solid #ccc; border-radius: 4px; background: #fff; cursor: pointer; - font-size: 0.9em; - vertical-align: middle; -} -#shareBtn.rdb-search-action-btn { margin-left: 6px; } - -/* ── Sort controls ─────────────────────────────────────────────────────── */ -#sort-controls { - margin-top: 1em; - margin-bottom: 8px; - font-size: 0.9em; color: #555; + transition: background 0.15s, color 0.15s; + position: relative; +} +.rdb-icon-btn:hover { + background: #f0f0f0; + color: #333; +} +.rdb-icon-btn svg { + display: block; } -#sort-controls a { margin-left: 6px; } /* ── Profile cards (author/institution cards in search results) ─────── */ #profileCards { @@ -154,10 +114,9 @@ /* ── Dark mode ─────────────────────────────────────────────────────────── */ @media (prefers-color-scheme: dark) { - html:not([data-theme="light"]) #searchBox { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } - html:not([data-theme="light"]) #searchBox:focus { border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } html:not([data-theme="light"]) #filters select { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } - html:not([data-theme="light"]) .rdb-search-action-btn { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } + html:not([data-theme="light"]) .rdb-icon-btn { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } + html:not([data-theme="light"]) .rdb-icon-btn:hover { background: #2a3038; color: #fff; } html:not([data-theme="light"]) #pagination button { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } html:not([data-theme="light"]) .profile-card { background: #23272d; border-color: #4a4f57; color: #d6d9dc; } html:not([data-theme="light"]) .profile-card:hover { border-color: #5a9cf5; } @@ -166,14 +125,12 @@ html:not([data-theme="light"]) .rdb-result-meta { color: #aab0b8; } html:not([data-theme="light"]) .rdb-badge { background: #2e3d2e; color: #c8e6c9; } html:not([data-theme="light"]) .rdb-badge--award { background: #3d3525; color: #ffe0b2; } - html:not([data-theme="light"]) #searchStatus { color: #aab0b8; } - html:not([data-theme="light"]) #sort-controls { color: #aab0b8; } + html:not([data-theme="light"]) .rdb-search-status { color: #aab0b8; } html:not([data-theme="light"]) #noResults { color: #888; } } -html[data-theme="dark"] #searchBox { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } -html[data-theme="dark"] #searchBox:focus { border-color: #5a9cf5; box-shadow: 0 4px 16px rgba(0,0,0,0.3); } html[data-theme="dark"] #filters select { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } -html[data-theme="dark"] .rdb-search-action-btn { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } +html[data-theme="dark"] .rdb-icon-btn { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } +html[data-theme="dark"] .rdb-icon-btn:hover { background: #2a3038; color: #fff; } html[data-theme="dark"] #pagination button { background: #1e2127; color: #d6d9dc; border-color: #4a4f57; } html[data-theme="dark"] .profile-card { background: #23272d; border-color: #4a4f57; color: #d6d9dc; } html[data-theme="dark"] .profile-card:hover { border-color: #5a9cf5; } @@ -182,6 +139,5 @@ html[data-theme="dark"] .rdb-result-authors { color: #aab0b8; } html[data-theme="dark"] .rdb-result-meta { color: #aab0b8; } html[data-theme="dark"] .rdb-badge { background: #2e3d2e; color: #c8e6c9; } html[data-theme="dark"] .rdb-badge--award { background: #3d3525; color: #ffe0b2; } -html[data-theme="dark"] #searchStatus { color: #aab0b8; } -html[data-theme="dark"] #sort-controls { color: #aab0b8; } +html[data-theme="dark"] .rdb-search-status { color: #aab0b8; } html[data-theme="dark"] #noResults { color: #888; } diff --git a/src/assets/js/reprodb-search.js b/src/assets/js/reprodb-search.js index 3a5057cf..3a46ea03 100644 --- a/src/assets/js/reprodb-search.js +++ b/src/assets/js/reprodb-search.js @@ -124,13 +124,25 @@ }); } - window.sortResults = function(field) { - if (sortField === field) { sortAsc = !sortAsc; } - else { sortField = field; sortAsc = true; } + window.sortResults = function(field, asc) { + sortField = field; + sortAsc = asc; doSort(); renderResults(); }; + function applySortFromSelect() { + var val = document.getElementById('sortSelect').value; + var parts = val.split('-'); + var field = parts[0]; + var asc = parts[1] === 'asc'; + sortField = field; + sortAsc = asc; + doSort(); + currentPage = 1; + renderResults(); + } + window.changePage = function(delta) { var maxPage = Math.ceil(filtered.length / pageSize); currentPage = Math.max(1, Math.min(maxPage, currentPage + delta)); @@ -151,8 +163,8 @@ var list = document.getElementById('resultsList'); var noRes = document.getElementById('noResults'); var pagination = document.getElementById('pagination'); - var sortCtrl = document.getElementById('sort-controls'); var status = document.getElementById('searchStatus'); + var hero = document.getElementById('search-hero'); var query = document.getElementById('searchBox').value.trim(); var cleaned = query.replace(/#(unavailable|awarded|github|zenodo|nourl)/g, '').trim(); var terms = normalizeText(cleaned).split(/\s+/).filter(function(t) { return t.length > 0; }); @@ -163,16 +175,18 @@ areaChecks.forEach(function(cb) { if (cb.checked) selAreas.push(cb.value); }); var areaVal = selAreas.length === 1 ? selAreas[0] : ''; - if (!query && !yearVal && !venueVal && !areaVal) { + var hasActiveSearch = !!(query || yearVal || venueVal || areaVal); + + // Collapse hero when there are results, expand when idle + if (hero) hero.classList.toggle('has-results', hasActiveSearch); + + if (!hasActiveSearch) { list.classList.add('rdb-hidden'); noRes.classList.add('rdb-hidden'); pagination.classList.add('rdb-hidden'); - sortCtrl.classList.add('rdb-hidden'); - document.getElementById('downloadBtn').classList.add('rdb-hidden'); - document.getElementById('shareBtn').classList.add('rdb-hidden'); document.getElementById('profileCards').classList.add('rdb-hidden'); document.getElementById('profileCards').innerHTML = ''; - status.textContent = allData.length + ' artifacts available. Type a query or select a filter to search.'; + status.textContent = allData.length + ' artifacts'; return; } @@ -185,13 +199,11 @@ list.classList.add('rdb-hidden'); noRes.classList.remove('rdb-hidden'); pagination.classList.add('rdb-hidden'); - sortCtrl.classList.add('rdb-hidden'); - document.getElementById('downloadBtn').classList.add('rdb-hidden'); - document.getElementById('shareBtn').classList.add('rdb-hidden'); // Still show profile cards even when no artifact results renderProfileCards(query, terms); var pcCount = document.getElementById('profileCards').querySelectorAll('.profile-card').length; - status.textContent = '0 artifact results' + (pcCount > 0 ? ' (' + pcCount + ' matching profile' + (pcCount !== 1 ? 's' : '') + ')' : ''); + var total = pcCount; + status.textContent = total + ' result' + (total !== 1 ? 's' : ''); return; } @@ -264,12 +276,9 @@ }); list.classList.remove('rdb-hidden'); - sortCtrl.classList.remove('rdb-hidden'); - var profileCardCount = document.getElementById('profileCards').querySelectorAll('.profile-card').length; - var statusExtra = profileCardCount > 0 ? ' (' + profileCardCount + ' matching profile' + (profileCardCount !== 1 ? 's' : '') + ')' : ''; - status.textContent = filtered.length + ' result' + (filtered.length !== 1 ? 's' : '') + ' found' + statusExtra; - document.getElementById('downloadBtn').classList.toggle('rdb-hidden', filtered.length <= 0); - document.getElementById('shareBtn').classList.toggle('rdb-hidden', filtered.length <= 0); + var profileCount = document.getElementById('profileCards').querySelectorAll('.profile-card').length; + var totalResults = filtered.length + profileCount; + status.textContent = totalResults + ' result' + (totalResults !== 1 ? 's' : ''); pagination.classList.toggle('rdb-hidden', maxPage <= 1); document.getElementById('pageInfo').textContent = 'Page ' + currentPage + ' of ' + maxPage; document.getElementById('prevBtn').disabled = currentPage <= 1; @@ -314,14 +323,19 @@ window.shareSearch = function() { var url = window.location.href; + var btn = document.getElementById('shareBtn'); if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(url).then(function() { - var btn = document.getElementById('shareBtn'); - btn.textContent = '✓ Copied!'; - setTimeout(function() { btn.textContent = '🔗 Share'; }, ReproDB.COPIED_FLASH_MS); + btn.title = 'Copied!'; + setTimeout(function() { btn.title = 'Copy search link'; }, ReproDB.COPIED_FLASH_MS); }); } else { - prompt('Copy this URL to share:', url); + var ta = document.createElement('textarea'); + ta.value = url; ta.style.position = 'fixed'; ta.style.opacity = '0'; + document.body.appendChild(ta); ta.select(); + document.execCommand('copy'); document.body.removeChild(ta); + btn.title = 'Copied!'; + setTimeout(function() { btn.title = 'Copy search link'; }, ReproDB.COPIED_FLASH_MS); } }; @@ -510,7 +524,7 @@ allData = data; buildSearchIndex(data); populateFilters(data); - document.getElementById('searchStatus').textContent = data.length + ' artifacts available. Type a query or select a filter to search.'; + document.getElementById('searchStatus').textContent = data.length + ' artifacts'; // Wire up events var debounceTimer; @@ -580,6 +594,7 @@ } document.getElementById('yearFilter').addEventListener('change', doSearch); document.getElementById('venueFilter').addEventListener('change', doSearch); + document.getElementById('sortSelect').addEventListener('change', applySortFromSelect); document.querySelectorAll('.areaCheck').forEach(function(cb) { cb.addEventListener('change', doSearch); }); diff --git a/src/assets/js/reprodb-utils.js b/src/assets/js/reprodb-utils.js index aad8b457..35e15c3f 100644 --- a/src/assets/js/reprodb-utils.js +++ b/src/assets/js/reprodb-utils.js @@ -21,7 +21,7 @@ R.COPIED_FLASH_MS = 1500; /** Default rows per page for Tabulator and ranking tables. */ - R.DEFAULT_PAGE_SIZE = 50; + R.DEFAULT_PAGE_SIZE = 20; /** Page-size selector options shown in table footers. */ R.PAGE_SIZE_OPTIONS = [10, 25, 50, 100]; diff --git a/src/index.md b/src/index.md index 6eecf041..1c302a96 100644 --- a/src/index.md +++ b/src/index.md @@ -3,40 +3,52 @@ title: "" skip_chartjs: true --- - - + -**Research artifacts & artifact evaluation (AE)** drive reproducibility and scientific impact. This project analyzes and makes accessible artifact evaluation outcomes across major [security]({{ '/security/' | relative_url }}) and [systems]({{ '/systems/' | relative_url }}) conferences, recognizing the contributions of both artifact authors and artifact evaluation committees. - -
-
- - - -
-
- - - - - - +
+
+

+ Research artifacts and artifact evaluation drive reproducibility and scientific impact. ReproDB aggregates and surfaces artifact evaluation outcomes across major security and systems conferences, recognizing the contributions of both artifact authors and artifact evaluation service. +

+
+
+ + + +
+
+ + + + + + + Loading… + + + + + +
+
-
Loading artifact data…
- - -
- -
- Sort by: - Year · - Title · - Venue
diff --git a/src/profile.md b/src/profile.md index 00c34f39..d44fa0c1 100644 --- a/src/profile.md +++ b/src/profile.md @@ -6,12 +6,12 @@ layout: default {% include profile_common.html %} -
-
-

Find a researcher or institution

+
+
+

Find a researcher or institution

- - + +