This is an automated email from the ASF dual-hosted git repository.

spetz pushed a commit to branch bench_ui_update
in repository https://gitbox.apache.org/repos/asf/iggy.git

commit e7bf114d6f6ac0fcfcdc0595a3999f1c7a6b6e56
Author: spetz <[email protected]>
AuthorDate: Tue Apr 21 11:08:36 2026 +0200

    refactor(bench): unify benchmarks list and fix best-pick selection
---
 assets/benchmarking_platform.png                   | Bin 1756918 -> 1165558 
bytes
 core/bench/dashboard/frontend/assets/style.css     | 250 +++++++++++--
 .../frontend/src/components/app_content.rs         |  46 ++-
 .../dashboard/frontend/src/components/footer.rs    |   4 +-
 .../frontend/src/components/layout/hero.rs         | 204 ++++++----
 .../frontend/src/components/layout/main_content.rs |  55 ++-
 .../frontend/src/components/layout/sidebar.rs      | 233 +++++++++---
 .../frontend/src/components/layout/top_app_bar.rs  |  88 +++--
 .../{benchmark_selector.rs => benchmarks_list.rs}  | 118 +++---
 .../src/components/selectors/gitref_selector.rs    |  63 ----
 .../src/components/selectors/hardware_selector.rs  |  61 ---
 .../frontend/src/components/selectors/mod.rs       |   5 +-
 .../selectors/recent_benchmarks_selector.rs        | 302 ---------------
 .../components/tooltips/benchmark_info_tooltip.rs  |  23 +-
 .../components/tooltips/server_stats_tooltip.rs    |   2 -
 core/bench/dashboard/frontend/src/main.rs          |   1 +
 .../dashboard/frontend/src/state/benchmark.rs      | 412 ++++++++++++++++++---
 core/bench/dashboard/frontend/src/state/ui.rs      |  25 +-
 core/bench/dashboard/frontend/src/version.rs       | 180 +++++++++
 core/bench/report/src/plotting/chart.rs            |  23 +-
 20 files changed, 1295 insertions(+), 800 deletions(-)

diff --git a/assets/benchmarking_platform.png b/assets/benchmarking_platform.png
index dfc9e8c71..de8d1a74a 100644
Binary files a/assets/benchmarking_platform.png and 
b/assets/benchmarking_platform.png differ
diff --git a/core/bench/dashboard/frontend/assets/style.css 
b/core/bench/dashboard/frontend/assets/style.css
index 2e87bfc80..077bbd14f 100644
--- a/core/bench/dashboard/frontend/assets/style.css
+++ b/core/bench/dashboard/frontend/assets/style.css
@@ -335,14 +335,15 @@ body {
 }
 
 .chart-title-identifier {
+    display: inline-flex;
+    align-items: center;
+    gap: 8px;
+    flex-wrap: wrap;
+    justify-content: center;
     font-size: var(--font-size-md, 0.75rem);
     color: var(--color-text-muted);
-    font-style: italic;
     font-weight: 500;
     margin-top: var(--spacing-sm);
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
     max-width: 100%;
     padding: 0 var(--spacing-sm);
     box-sizing: border-box;
@@ -352,6 +353,35 @@ body.dark .chart-title-identifier {
     color: var(--color-dark-text-secondary);
 }
 
+.chart-title-sep {
+    opacity: 0.5;
+}
+
+.chart-title-gitref {
+    display: inline-flex;
+    align-items: center;
+    gap: 5px;
+    padding: 2px 8px;
+    border-radius: 999px;
+    background: rgba(255, 145, 3, 0.1);
+    color: #ff9103;
+    font-weight: 600;
+    font-style: normal;
+    text-decoration: none;
+    border: 1px solid rgba(255, 145, 3, 0.25);
+    transition: background 140ms ease, border-color 140ms ease, transform 
140ms ease;
+}
+
+.chart-title-gitref:hover {
+    background: rgba(255, 145, 3, 0.18);
+    border-color: rgba(255, 145, 3, 0.5);
+    transform: translateY(-1px);
+}
+
+.chart-title-gitref svg {
+    opacity: 0.75;
+}
+
 .single-view {
     flex: 1;
     min-height: 0;
@@ -562,6 +592,33 @@ body.dark .app-bar {
     display: inline-flex;
 }
 
+.app-bar-toast {
+    position: absolute;
+    top: calc(100% + 8px);
+    right: 0;
+    padding: 5px 10px;
+    background: #111827;
+    color: #fff;
+    font-size: 11px;
+    font-weight: 600;
+    border-radius: 6px;
+    white-space: nowrap;
+    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
+    pointer-events: none;
+    animation: app-bar-toast-in 160ms ease;
+    z-index: 40;
+}
+
+body.dark .app-bar-toast {
+    background: #f5f5f5;
+    color: #0b1220;
+}
+
+@keyframes app-bar-toast-in {
+    from { opacity: 0; transform: translateY(-4px); }
+    to { opacity: 1; transform: translateY(0); }
+}
+
 .app-bar-brand {
     display: inline-flex;
     align-items: center;
@@ -1098,6 +1155,17 @@ body.dark .segment.active {
     font-size: 11px;
 }
 
+.footer-meta a {
+    color: var(--color-text-secondary);
+    text-decoration: none;
+    font-weight: 500;
+    transition: color 150ms;
+}
+
+.footer-meta a:hover {
+    color: #ff9103;
+}
+
 .footer-version {
     padding: 2px 6px;
     background: var(--color-border);
@@ -1652,44 +1720,50 @@ body.dark .sidebar-search-hint {
     background: rgba(255, 255, 255, 0.08);
 }
 
-.sidebar-scope {
+.sidebar-facet-row {
     display: grid;
     grid-template-columns: 1fr 1fr;
-    gap: 2px;
-    padding: 3px;
-    background: var(--color-border);
-    border-radius: 8px;
+    gap: 8px;
 }
 
-body.dark .sidebar-scope {
-    background: rgba(255, 255, 255, 0.04);
+.sidebar-facet {
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+    min-width: 0;
 }
 
-.sidebar-scope-btn {
-    padding: 7px 10px;
-    background: transparent;
-    border: none;
-    border-radius: 6px;
+.sidebar-facet-label {
+    font-size: 10px;
+    font-weight: 700;
+    text-transform: uppercase;
+    letter-spacing: 0.1em;
     color: var(--color-text-secondary);
-    font-family: inherit;
-    font-size: 12.5px;
-    font-weight: 500;
-    cursor: pointer;
-    transition: all 150ms;
 }
 
-.sidebar-scope-btn:hover {
+.sidebar-facet-select {
+    width: 100%;
+    padding: 6px 8px;
+    font-size: 12px;
+    font-family: inherit;
+    background: var(--color-background);
     color: var(--color-text);
+    border: 1px solid var(--color-border);
+    border-radius: 6px;
+    cursor: pointer;
+    transition: border-color 150ms;
 }
 
-.sidebar-scope-btn.active {
-    background: var(--color-background);
-    color: var(--color-text);
-    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+.sidebar-facet-select:hover,
+.sidebar-facet-select:focus {
+    border-color: #ff9103;
+    outline: none;
 }
 
-body.dark .sidebar-scope-btn.active {
-    background: var(--color-dark-background);
+body.dark .sidebar-facet-select {
+    background: var(--color-dark-input);
+    color: var(--color-dark-text);
+    border-color: var(--color-dark-border);
 }
 
 .sidebar-kind-chips {
@@ -2220,6 +2294,82 @@ body.dark .hero-v2 {
     line-height: 1.5;
 }
 
+.hero-v2-loading {
+    justify-content: center;
+    align-items: center;
+    min-height: 520px;
+}
+
+.hero-v2-loading-inner {
+    position: relative;
+    z-index: 1;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    gap: 14px;
+    text-align: center;
+    max-width: 520px;
+    padding: 0 24px;
+}
+
+.hero-v2-loading-mark {
+    width: 112px;
+    height: 112px;
+    object-fit: contain;
+    filter: drop-shadow(0 0 24px rgba(255, 145, 3, 0.35));
+    animation: hero-loading-pulse 1800ms ease-in-out infinite;
+}
+
+.hero-v2-loading-brand {
+    font-family: var(--hero-mono);
+    font-size: 11px;
+    font-weight: 600;
+    letter-spacing: 0.22em;
+    text-transform: uppercase;
+    color: #ff9103;
+    margin-top: 4px;
+}
+
+.hero-v2-loading-sub {
+    font-size: clamp(28px, 4vw, 44px);
+    font-weight: 800;
+    letter-spacing: -0.02em;
+    color: var(--hero-text);
+    line-height: 1;
+}
+
+.hero-v2-loading-slow {
+    margin: 8px 0 0;
+    color: var(--hero-muted);
+    font-size: 13px;
+    line-height: 1.5;
+    animation: hero-fade-in 400ms ease both;
+}
+
+@keyframes hero-loading-pulse {
+    0%, 100% {
+        opacity: 0.4;
+        transform: scale(0.96);
+    }
+    50% {
+        opacity: 1;
+        transform: scale(1);
+    }
+}
+
+.visually-hidden {
+    position: absolute;
+    width: 1px;
+    height: 1px;
+    padding: 0;
+    margin: -1px;
+    overflow: hidden;
+    clip: rect(0, 0, 0, 0);
+    white-space: nowrap;
+    border: 0;
+}
+
 .hero-v2-headline {
     display: flex;
     flex-direction: column;
@@ -2271,6 +2421,39 @@ body.dark .hero-v2 {
     font-family: var(--hero-mono);
     font-size: 13px;
     letter-spacing: 0.02em;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    gap: 0 6px;
+}
+
+.hero-v2-sub-sep {
+    color: var(--hero-muted);
+    opacity: 0.6;
+}
+
+.hero-v2-sub-gitref {
+    display: inline-flex;
+    align-items: center;
+    gap: 5px;
+    padding: 2px 8px;
+    border-radius: 999px;
+    background: rgba(255, 145, 3, 0.1);
+    color: #ff9103;
+    font-weight: 600;
+    text-decoration: none;
+    border: 1px solid rgba(255, 145, 3, 0.25);
+    transition: background 140ms ease, border-color 140ms ease, transform 
140ms ease;
+}
+
+.hero-v2-sub-gitref:hover {
+    background: rgba(255, 145, 3, 0.18);
+    border-color: rgba(255, 145, 3, 0.5);
+    transform: translateY(-1px);
+}
+
+.hero-v2-sub-gitref svg {
+    opacity: 0.75;
 }
 
 .hero-v2-tagline {
@@ -2959,6 +3142,17 @@ body.dark .benchmark-meta-chip {
 .benchmark-meta-chip.flavor-latency .benchmark-meta-chip-label { color: 
#ff9103; opacity: 0.85; }
 .benchmark-meta-chip.flavor-throughput .benchmark-meta-chip-label { color: 
#38bdf8; opacity: 0.85; }
 
+.compare-pane .benchmark-meta-row {
+    grid-template-columns: 1fr;
+    gap: 4px;
+    align-items: start;
+}
+
+.compare-pane .benchmark-meta-label {
+    border-right: none;
+    padding-right: 0;
+}
+
 @media (max-width: 720px) {
     .benchmark-meta-row {
         grid-template-columns: 1fr;
diff --git a/core/bench/dashboard/frontend/src/components/app_content.rs 
b/core/bench/dashboard/frontend/src/components/app_content.rs
index 5ecb741aa..e3dc1a3c6 100644
--- a/core/bench/dashboard/frontend/src/components/app_content.rs
+++ b/core/bench/dashboard/frontend/src/components/app_content.rs
@@ -218,23 +218,35 @@ pub fn app_content() -> Html {
         gitref_ctx.state.selected_gitref.clone(),
     );
 
-    let on_gitref_select = {
-        let gitref_dispatch = gitref_ctx.dispatch.clone();
-        Callback::from(move |gitref: String| {
-            
gitref_dispatch.emit(GitrefAction::SetSelectedGitref(Some(gitref)));
-        })
-    };
-
-    let on_hardware_select = {
-        let hardware_dispatch = hardware_ctx.dispatch.clone();
+    {
+        let selected_uuid = benchmark_ctx
+            .state
+            .selected_benchmark
+            .as_ref()
+            .map(|benchmark| benchmark.uuid.to_string());
+        let route_uuid = match route.as_ref() {
+            Some(AppRoute::Benchmark { uuid }) => Some(uuid.clone()),
+            _ => None,
+        };
         let navigator = navigator.clone();
-        Callback::from(move |hardware_id: String| {
-            
hardware_dispatch.emit(HardwareAction::SelectHardware(Some(hardware_id)));
-            if let Some(nav) = navigator.as_ref() {
-                nav.push(&AppRoute::Home);
-            }
-        })
-    };
+        let is_loading_handle = is_loading_from_url.clone();
+        use_effect_with(
+            (selected_uuid, route_uuid),
+            move |(selected_uuid, route_uuid)| {
+                if *is_loading_handle {
+                    return;
+                }
+                if let (Some(selected), Some(current)) = (selected_uuid, 
route_uuid)
+                    && selected != current
+                    && let Some(nav) = navigator.as_ref()
+                {
+                    nav.push(&AppRoute::Benchmark {
+                        uuid: selected.clone(),
+                    });
+                }
+            },
+        );
+    }
 
     let show_detail = matches!(
         route,
@@ -250,7 +262,7 @@ pub fn app_content() -> Html {
         )}>
             <TopAppBar show_sidebar_toggle={show_detail} 
show_detail_actions={show_detail} />
             if show_detail {
-                <Sidebar on_gitref_select={on_gitref_select} 
on_hardware_select={on_hardware_select} />
+                <Sidebar />
                 <MainContent 
selected_gitref={gitref_ctx.state.selected_gitref.clone().unwrap_or_default()} 
/>
             } else {
                 <Hero 
selected_gitref={gitref_ctx.state.selected_gitref.clone().unwrap_or_default()} 
/>
diff --git a/core/bench/dashboard/frontend/src/components/footer.rs 
b/core/bench/dashboard/frontend/src/components/footer.rs
index 8bd5d2d95..58cfd6f0f 100644
--- a/core/bench/dashboard/frontend/src/components/footer.rs
+++ b/core/bench/dashboard/frontend/src/components/footer.rs
@@ -41,7 +41,9 @@ pub fn footer() -> Html {
                 <div class="footer-meta">
                     <span 
class="footer-version">{"v"}{env!("CARGO_PKG_VERSION")}</span>
                     <span class="footer-sep">{"•"}</span>
-                    <span>{"Apache Software Foundation"}</span>
+                    <a href="https://www.apache.org/"; target="_blank" 
rel="noopener noreferrer">
+                        {"Apache Software Foundation"}
+                    </a>
                 </div>
             </div>
         </footer>
diff --git a/core/bench/dashboard/frontend/src/components/layout/hero.rs 
b/core/bench/dashboard/frontend/src/components/layout/hero.rs
index a558f73f3..a5905d87a 100644
--- a/core/bench/dashboard/frontend/src/components/layout/hero.rs
+++ b/core/bench/dashboard/frontend/src/components/layout/hero.rs
@@ -17,15 +17,14 @@
 
 use crate::api;
 use crate::components::chart::tail_chart::TailChart;
-use crate::format::{format_ms, nan_safe_cmp};
+use crate::format::format_ms;
 use crate::router::AppRoute;
-use crate::state::benchmark::{pick_best_from_recent_batch, use_benchmark};
+use crate::state::benchmark::{latest_sweep, pick_best_from_recent_batch, 
use_benchmark};
 use bench_dashboard_shared::BenchmarkReportLight;
-use bench_report::benchmark_kind::BenchmarkKind;
 use chrono::DateTime;
 use gloo::console::log;
+use gloo::timers::callback::Timeout;
 use std::cell::Cell;
-use std::collections::BTreeMap;
 use std::rc::Rc;
 use yew::platform::spawn_local;
 use yew::prelude::*;
@@ -40,10 +39,14 @@ pub struct HeroProps {
 pub fn hero(props: &HeroProps) -> Html {
     let benchmark_ctx = use_benchmark();
     let navigator = use_navigator();
+    let (is_dark, _) = use_context::<(bool, Callback<()>)>().expect("Theme 
context not found");
     let recent = use_state(Vec::<BenchmarkReportLight>::new);
+    let is_loading = use_state(|| true);
+    let is_slow = use_state(|| false);
 
     {
         let recent = recent.clone();
+        let is_loading = is_loading.clone();
         let cancelled = Rc::new(Cell::new(false));
         let cancelled_async = cancelled.clone();
         use_effect_with((), move |_| {
@@ -52,49 +55,46 @@ pub fn hero(props: &HeroProps) -> Html {
                     Ok(data) => {
                         if !cancelled_async.get() {
                             recent.set(data);
+                            is_loading.set(false);
+                        }
+                    }
+                    Err(error) => {
+                        log!(format!("Hero: fetch_recent_benchmarks failed: 
{}", error));
+                        if !cancelled_async.get() {
+                            is_loading.set(false);
                         }
                     }
-                    Err(error) => log!(format!("Hero: fetch_recent_benchmarks 
failed: {}", error)),
                 }
             });
             move || cancelled.set(true)
         });
     }
 
-    let recent_vec = (*recent).clone();
-    let source: Vec<&BenchmarkReportLight> = if recent_vec.is_empty() {
-        benchmark_ctx.state.entries.values().flatten().collect()
-    } else {
-        recent_vec.iter().collect()
-    };
-    let unrestricted: Vec<&BenchmarkReportLight> = source
-        .iter()
-        .copied()
-        .filter(|benchmark| benchmark.params.rate_limit.is_none())
-        .collect();
-    let mut stats = compute_stats(unrestricted.iter().copied());
-    stats.showcase = unrestricted
-        .iter()
-        .copied()
-        .max_by(|left, right| nan_safe_cmp(throughput_mb(left), 
throughput_mb(right)))
-        .cloned();
-    if stats.showcase.is_none() && !source.is_empty() {
-        stats.showcase = pick_best_from_recent_batch(&source);
+    {
+        let is_slow = is_slow.clone();
+        let is_loading_value = *is_loading;
+        use_effect_with(is_loading_value, move |loading| {
+            if !*loading {
+                is_slow.set(false);
+                return Box::new(|| ()) as Box<dyn FnOnce()>;
+            }
+            let timeout = Timeout::new(2_000, move || is_slow.set(true));
+            Box::new(move || drop(timeout)) as Box<dyn FnOnce()>
+        });
+    }
+
+    if *is_loading {
+        return render_hero_loading(is_dark, *is_slow);
     }
 
+    let recent_vec = (*recent).clone();
+    let source: Vec<&BenchmarkReportLight> = recent_vec.iter().collect();
+    let sweep = latest_sweep(&source);
+    let mut stats = compute_stats(sweep.iter().copied());
+    stats.showcase = pick_best_from_recent_batch(&source);
+
     if stats.total == 0 {
-        return html! {
-            <div class="hero-v2 hero-v2-empty">
-                { render_background_grid() }
-                <div class="hero-v2-empty-inner">
-                    <div class="hero-v2-eyebrow">{"Apache Iggy"}</div>
-                    <h1 class="hero-v2-empty-title">{"Benchmarks"}</h1>
-                    <p class="hero-v2-empty-sub">
-                        {"Pick a hardware and gitref in the sidebar to view 
performance data."}
-                    </p>
-                </div>
-            </div>
-        };
+        return render_hero_loading(is_dark, true);
     }
 
     let hardware = benchmark_ctx
@@ -102,11 +102,12 @@ pub fn hero(props: &HeroProps) -> Html {
         .current_hardware
         .clone()
         .unwrap_or_default();
-    let gitref_suffix = if props.selected_gitref.is_empty() {
-        String::new()
-    } else {
-        format!(" @ {}", props.selected_gitref)
-    };
+    let sweep_gitref = stats
+        .showcase
+        .as_ref()
+        .and_then(|showcase| showcase.params.gitref.clone())
+        .filter(|gitref| !gitref.is_empty())
+        .or_else(|| Some(props.selected_gitref.clone()).filter(|gitref| 
!gitref.is_empty()));
 
     let on_view_details = stats.showcase.as_ref().map(|showcase| {
         let uuid = showcase.uuid.to_string();
@@ -119,19 +120,14 @@ pub fn hero(props: &HeroProps) -> Html {
     });
 
     let on_browse_click = {
-        let latest_uuid = 
latest_uuid_from_entries(&benchmark_ctx.state.entries);
         let navigator = navigator.clone();
         Callback::from(move |_: MouseEvent| {
-            if let Some(uuid) = latest_uuid.clone() {
-                navigate_to_benchmark(&navigator, uuid);
-            } else {
-                let navigator = navigator.clone();
-                spawn_local(async move {
-                    if let Some(uuid) = fetch_latest_uuid().await {
-                        navigate_to_benchmark(&navigator, uuid);
-                    }
-                });
-            }
+            let navigator = navigator.clone();
+            spawn_local(async move {
+                if let Some(uuid) = fetch_latest_uuid().await {
+                    navigate_to_benchmark(&navigator, uuid);
+                }
+            });
         })
     };
 
@@ -139,7 +135,7 @@ pub fn hero(props: &HeroProps) -> Html {
         <div class="hero-v2">
             { render_background_grid() }
             <div class="hero-v2-inner">
-                { render_headline(&stats, &hardware, &gitref_suffix, 
&on_browse_click) }
+                { render_headline(&stats, &hardware, sweep_gitref.as_deref(), 
&on_browse_click) }
                 { render_stat_cards(&stats) }
                 {
                     match (stats.showcase.as_ref(), on_view_details) {
@@ -157,16 +153,6 @@ pub fn hero(props: &HeroProps) -> Html {
     }
 }
 
-fn latest_uuid_from_entries(
-    entries: &BTreeMap<BenchmarkKind, Vec<BenchmarkReportLight>>,
-) -> Option<String> {
-    entries
-        .values()
-        .flatten()
-        .max_by(|left, right| left.timestamp.cmp(&right.timestamp))
-        .map(|benchmark| benchmark.uuid.to_string())
-}
-
 async fn fetch_latest_uuid() -> Option<String> {
     match api::fetch_recent_benchmarks(Some(1)).await {
         Ok(recent) => recent.into_iter().next().map(|b| b.uuid.to_string()),
@@ -273,7 +259,7 @@ fn render_background_grid() -> Html {
 fn render_headline(
     stats: &HeroStats,
     hardware: &str,
-    gitref_suffix: &str,
+    gitref: Option<&str>,
     on_browse_click: &Callback<MouseEvent>,
 ) -> Html {
     let (value, unit, subject) = match &stats.peak_mb_s {
@@ -283,11 +269,6 @@ fn render_headline(
         }
         None => ("-".to_string(), "MB/s", String::new()),
     };
-    let sub = if subject.is_empty() {
-        format!("{hardware}{gitref_suffix}")
-    } else {
-        format!("{subject} · {hardware}{gitref_suffix}")
-    };
 
     html! {
         <div class="hero-v2-headline">
@@ -296,7 +277,9 @@ fn render_headline(
                 <span class="hero-v2-big">{value}</span>
                 <span class="hero-v2-unit">{unit}</span>
             </h1>
-            <p class="hero-v2-sub">{sub}</p>
+            <p class="hero-v2-sub">
+                { render_hero_sub(&subject, hardware, gitref) }
+            </p>
             <p class="hero-v2-tagline">
                 {"Modern hardware is incredibly capable. "}
                 <span class="hero-v2-tagline-accent">{"Apache Iggy was built 
for it."}</span>
@@ -319,6 +302,50 @@ fn render_headline(
     }
 }
 
+fn render_hero_sub(subject: &str, hardware: &str, gitref: Option<&str>) -> 
Html {
+    let prefix = match (subject.is_empty(), hardware.is_empty()) {
+        (true, true) => String::new(),
+        (true, false) => hardware.to_string(),
+        (false, true) => subject.to_string(),
+        (false, false) => format!("{subject} · {hardware}"),
+    };
+    let has_prefix = !prefix.is_empty();
+    let gitref = gitref.map(str::to_string);
+    let gitref_owned = gitref.clone();
+
+    html! {
+        <>
+            if has_prefix {
+                <span>{prefix}</span>
+            }
+            if let Some(gitref) = gitref_owned {
+                if has_prefix {
+                    <span class="hero-v2-sub-sep">{" @ "}</span>
+                }
+                <a
+                    class="hero-v2-sub-gitref"
+                    href={iggy_gitref_url(&gitref)}
+                    target="_blank"
+                    rel="noopener noreferrer"
+                    title={format!("Browse apache/iggy at {gitref}")}
+                >
+                    {gitref}
+                    <svg xmlns="http://www.w3.org/2000/svg"; width="11" 
height="11" viewBox="0 0 24 24"
+                         fill="none" stroke="currentColor" stroke-width="2" 
stroke-linecap="round" stroke-linejoin="round">
+                        <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 
0 0 1 2-2h6" />
+                        <polyline points="15 3 21 3 21 9" />
+                        <line x1="10" y1="14" x2="21" y2="3" />
+                    </svg>
+                </a>
+            }
+        </>
+    }
+}
+
+fn iggy_gitref_url(gitref: &str) -> String {
+    format!("https://github.com/apache/iggy/tree/{gitref}";)
+}
+
 fn render_stat_cards(stats: &HeroStats) -> Html {
     html! {
         <div class="hero-v2-cards">
@@ -404,14 +431,6 @@ fn render_showcase_card(stagger: usize, showcase: 
Option<&BenchmarkReportLight>)
     }
 }
 
-fn throughput_mb(benchmark: &BenchmarkReportLight) -> f64 {
-    benchmark
-        .group_metrics
-        .first()
-        .map(|metrics| metrics.summary.total_throughput_megabytes_per_second)
-        .unwrap_or(0.0)
-}
-
 fn render_summary_card(stagger: usize, total: usize, latest_ts: Option<&str>) 
-> Html {
     let sub = match latest_ts {
         Some(ts) => format!("Latest: {}", format_date(ts)),
@@ -467,3 +486,32 @@ fn format_date(timestamp_str: &str) -> String {
         Err(_) => "unknown".to_string(),
     }
 }
+
+fn render_hero_loading(is_dark: bool, is_slow: bool) -> Html {
+    let logo_src = if is_dark {
+        "/assets/iggy-light.png"
+    } else {
+        "/assets/iggy-dark.png"
+    };
+    html! {
+        <div class="hero-v2 hero-v2-loading" aria-busy="true" 
aria-live="polite">
+            { render_background_grid() }
+            <div class="hero-v2-loading-inner">
+                <img
+                    class="hero-v2-loading-mark"
+                    src={logo_src}
+                    alt=""
+                    aria-hidden="true"
+                />
+                <div class="hero-v2-loading-brand">{"Apache Iggy"}</div>
+                <div class="hero-v2-loading-sub">{"Benchmarks"}</div>
+                if is_slow {
+                    <p class="hero-v2-loading-slow">
+                        {"Fetching the latest benchmark run. This can take a 
moment on a cold cache."}
+                    </p>
+                }
+                <span class="visually-hidden">{"Loading benchmarks"}</span>
+            </div>
+        </div>
+    }
+}
diff --git 
a/core/bench/dashboard/frontend/src/components/layout/main_content.rs 
b/core/bench/dashboard/frontend/src/components/layout/main_content.rs
index 766b53e9f..6b9a796d8 100644
--- a/core/bench/dashboard/frontend/src/components/layout/main_content.rs
+++ b/core/bench/dashboard/frontend/src/components/layout/main_content.rs
@@ -22,7 +22,7 @@ use crate::components::layout::sweep_view::SweepView;
 use crate::components::selectors::measurement_type_selector::MeasurementType;
 use crate::router::AppRoute;
 use crate::state::benchmark::use_benchmark;
-use crate::state::ui::{UiAction, ViewMode, use_ui};
+use crate::state::ui::{UiAction, use_ui};
 use bench_dashboard_shared::BenchmarkReportLight;
 use bench_report::benchmark_kind::BenchmarkKind;
 use std::collections::BTreeMap;
@@ -40,7 +40,6 @@ pub fn main_content(props: &MainContentProps) -> Html {
     let _ = &props.selected_gitref;
     let benchmark_ctx = use_benchmark();
     let ui = use_ui();
-    let is_recent_view = matches!(ui.view_mode, ViewMode::RecentBenchmarks);
     let selected = benchmark_ctx.state.selected_benchmark.clone();
     let pinned = ui.compare_pin.clone();
     let entries = benchmark_ctx.state.entries.clone();
@@ -101,7 +100,6 @@ pub fn main_content(props: &MainContentProps) -> Html {
             is_dark,
             &entries,
         ),
-        (None, _) if is_recent_view => render_empty_recent(),
         (None, _) => render_loading(),
     };
 
@@ -121,7 +119,7 @@ fn render_single(
                     { benchmark.title(&measurement.to_string()) }
                 </div>
                 <div class="chart-title-identifier">
-                    { benchmark.identifier_with_cpu_and_version() }
+                    { render_benchmark_identifier(benchmark) }
                 </div>
             </div>
             <BenchmarkMeta benchmark={benchmark.clone()} />
@@ -215,7 +213,7 @@ fn render_compare_pane(
                     { benchmark.title(&measurement.to_string()) }
                 </div>
                 <div class="chart-title-identifier">
-                    { benchmark.identifier_with_cpu_and_version() }
+                    { render_benchmark_identifier(benchmark) }
                 </div>
             </div>
             <BenchmarkMeta benchmark={benchmark.clone()} />
@@ -226,27 +224,52 @@ fn render_compare_pane(
     }
 }
 
-fn render_empty_recent() -> Html {
+fn render_loading() -> Html {
     html! {
         <div class="content-wrapper">
             <div class="empty-state">
                 <div class="empty-state-content">
-                    <h2>{"Select a recent benchmark"}</h2>
-                    <p>{"Choose a benchmark from the sidebar to display 
performance data."}</p>
+                    <h2>{"Loading benchmark..."}</h2>
                 </div>
             </div>
         </div>
     }
 }
 
-fn render_loading() -> Html {
+fn render_benchmark_identifier(benchmark: &BenchmarkReportLight) -> Html {
+    let hardware = benchmark
+        .hardware
+        .identifier
+        .as_deref()
+        .unwrap_or("identifier");
+    let cpu = benchmark.hardware.cpu_name.as_str();
+    let gitref = benchmark
+        .params
+        .gitref
+        .as_deref()
+        .filter(|gitref| !gitref.is_empty());
+
     html! {
-        <div class="content-wrapper">
-            <div class="empty-state">
-                <div class="empty-state-content">
-                    <h2>{"Loading benchmark..."}</h2>
-                </div>
-            </div>
-        </div>
+        <>
+            <span>{format!("{hardware} @ {cpu}")}</span>
+            if let Some(gitref) = gitref {
+                <span class="chart-title-sep">{"·"}</span>
+                <a
+                    class="chart-title-gitref"
+                    
href={format!("https://github.com/apache/iggy/tree/{gitref}";)}
+                    target="_blank"
+                    rel="noopener noreferrer"
+                    title={format!("Browse apache/iggy at {gitref}")}
+                >
+                    {gitref}
+                    <svg xmlns="http://www.w3.org/2000/svg"; width="11" 
height="11" viewBox="0 0 24 24"
+                         fill="none" stroke="currentColor" stroke-width="2" 
stroke-linecap="round" stroke-linejoin="round">
+                        <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 
0 0 1 2-2h6" />
+                        <polyline points="15 3 21 3 21 9" />
+                        <line x1="10" y1="14" x2="21" y2="3" />
+                    </svg>
+                </a>
+            }
+        </>
     }
 }
diff --git a/core/bench/dashboard/frontend/src/components/layout/sidebar.rs 
b/core/bench/dashboard/frontend/src/components/layout/sidebar.rs
index c71dd7457..72aba0a59 100644
--- a/core/bench/dashboard/frontend/src/components/layout/sidebar.rs
+++ b/core/bench/dashboard/frontend/src/components/layout/sidebar.rs
@@ -15,29 +15,79 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::components::selectors::benchmark_selector::BenchmarkSelector;
-use crate::components::selectors::gitref_selector::GitrefSelector;
-use crate::components::selectors::hardware_selector::HardwareSelector;
+use crate::api;
+use crate::components::selectors::benchmarks_list::BenchmarksList;
 use crate::components::selectors::param_filters_panel::ParamFiltersPanel;
-use 
crate::components::selectors::recent_benchmarks_selector::RecentBenchmarksSelector;
-use crate::state::gitref::use_gitref;
-use crate::state::ui::{KindGroup, SidebarSort, UiAction, ViewMode, use_ui};
+use crate::router::AppRoute;
+use crate::state::benchmark::{BenchmarkAction, recency_cmp, use_benchmark};
+use crate::state::ui::{KindGroup, SidebarSort, UiAction, use_ui};
+use bench_dashboard_shared::BenchmarkReportLight;
+use gloo::console::log;
+use std::cell::Cell;
+use std::collections::BTreeSet;
+use std::rc::Rc;
 use web_sys::HtmlInputElement;
+use web_sys::HtmlSelectElement;
+use yew::platform::spawn_local;
 use yew::prelude::*;
+use yew_router::prelude::{use_navigator, use_route};
+
+const RECENT_LIMIT: u32 = 10_000;
 
 #[derive(Properties, PartialEq)]
-pub struct SidebarProps {
-    pub on_gitref_select: Callback<String>,
-    pub on_hardware_select: Callback<String>,
-}
+pub struct SidebarProps;
 
 #[function_component(Sidebar)]
-pub fn sidebar(props: &SidebarProps) -> Html {
-    let gitref_ctx = use_gitref();
+pub fn sidebar(_props: &SidebarProps) -> Html {
     let ui = use_ui();
-    let is_recent_view = matches!(ui.view_mode, ViewMode::RecentBenchmarks);
-    let active_kind_filter = ui.sidebar_kind_filter.clone();
-    let current_sort = ui.sidebar_sort;
+    let benchmark_ctx = use_benchmark();
+    let navigator = use_navigator();
+    let route = use_route::<AppRoute>();
+
+    let benchmarks = use_state(Vec::<BenchmarkReportLight>::new);
+    let is_loading = use_state(|| true);
+
+    {
+        let benchmarks_handle = benchmarks.clone();
+        let is_loading_handle = is_loading.clone();
+        let dispatch = benchmark_ctx.dispatch.clone();
+        let navigator = navigator.clone();
+        let url_has_benchmark = matches!(
+            route,
+            Some(AppRoute::Benchmark { .. }) | Some(AppRoute::Compare { .. })
+        );
+        let cancelled = Rc::new(Cell::new(false));
+        let cancelled_async = cancelled.clone();
+        use_effect_with((), move |_| {
+            spawn_local(async move {
+                match api::fetch_recent_benchmarks(Some(RECENT_LIMIT)).await {
+                    Ok(mut data) => {
+                        data.sort_by(|left, right| {
+                            recency_cmp(right, left).then_with(|| 
right.uuid.cmp(&left.uuid))
+                        });
+                        if cancelled_async.get() {
+                            return;
+                        }
+                        if !url_has_benchmark && let Some(newest) = 
data.first().cloned() {
+                            if let Some(nav) = navigator.as_ref() {
+                                nav.push(&AppRoute::Benchmark {
+                                    uuid: newest.uuid.to_string(),
+                                });
+                            }
+                            
dispatch.emit(BenchmarkAction::SelectBenchmark(Box::new(Some(newest))));
+                        }
+                        benchmarks_handle.set(data);
+                    }
+                    Err(error) => log!(format!("Sidebar: 
fetch_recent_benchmarks failed: {error}")),
+                }
+                if !cancelled_async.get() {
+                    is_loading_handle.set(false);
+                }
+            });
+            move || cancelled.set(true)
+        });
+    }
+
     let current_search = ui.sidebar_search.clone();
 
     let on_search = {
@@ -55,11 +105,6 @@ pub fn sidebar(props: &SidebarProps) -> Html {
         })
     };
 
-    let on_scope_change = |mode: ViewMode| {
-        let ui = ui.clone();
-        Callback::from(move |_: MouseEvent| 
ui.dispatch(UiAction::SetViewMode(mode.clone())))
-    };
-
     let on_kind_toggle = {
         let ui = ui.clone();
         Callback::from(move |group: KindGroup| 
ui.dispatch(UiAction::ToggleKindFilter(group)))
@@ -81,6 +126,33 @@ pub fn sidebar(props: &SidebarProps) -> Html {
         })
     };
 
+    let on_hardware_change = {
+        let ui = ui.clone();
+        Callback::from(move |event: Event| {
+            let input: HtmlSelectElement = event.target_unchecked_into();
+            let value = input.value();
+            let next = if value.is_empty() { None } else { Some(value) };
+            ui.dispatch(UiAction::SetHardwareFilter(next));
+        })
+    };
+
+    let on_gitref_change = {
+        let ui = ui.clone();
+        Callback::from(move |event: Event| {
+            let input: HtmlSelectElement = event.target_unchecked_into();
+            let value = input.value();
+            let next = if value.is_empty() { None } else { Some(value) };
+            ui.dispatch(UiAction::SetGitrefFilter(next));
+        })
+    };
+
+    let hardware_options = collect_hardware(&benchmarks);
+    let gitref_options = collect_gitrefs(&benchmarks, 
ui.hardware_filter.as_deref());
+    let active_kind_filter = ui.sidebar_kind_filter.clone();
+    let current_sort = ui.sidebar_sort;
+    let current_hardware = ui.hardware_filter.clone().unwrap_or_default();
+    let current_gitref = ui.gitref_filter.clone().unwrap_or_default();
+
     html! {
         <aside class="sidebar">
             <div class="sidebar-fixed-header">
@@ -94,7 +166,7 @@ pub fn sidebar(props: &SidebarProps) -> Html {
                     <input
                         type="search"
                         class="sidebar-search-input"
-                        placeholder="Search benchmarks, gitrefs, hardware..."
+                        placeholder="Search benchmarks..."
                         value={current_search.clone()}
                         oninput={on_search}
                     />
@@ -110,35 +182,41 @@ pub fn sidebar(props: &SidebarProps) -> Html {
                     }
                 </div>
 
-                <div class="sidebar-scope" role="tablist">
-                    <button
-                        type="button"
-                        role="tab"
-                        aria-selected={(!is_recent_view).to_string()}
-                        class={classes!("sidebar-scope-btn", 
(!is_recent_view).then_some("active"))}
-                        onclick={on_scope_change(ViewMode::SingleGitref)}
-                    >
-                        {"Version"}
-                    </button>
-                    <button
-                        type="button"
-                        role="tab"
-                        aria-selected={is_recent_view.to_string()}
-                        class={classes!("sidebar-scope-btn", 
is_recent_view.then_some("active"))}
-                        onclick={on_scope_change(ViewMode::RecentBenchmarks)}
-                    >
-                        {"Recent"}
-                    </button>
-                </div>
+                <div class="sidebar-facet-row">
+                    <label class="sidebar-facet">
+                        <span class="sidebar-facet-label">{"Hardware"}</span>
+                        <select class="sidebar-facet-select" 
onchange={on_hardware_change}>
+                            <option value="" 
selected={current_hardware.is_empty()}>
+                                {"All"}
+                            </option>
+                            { for hardware_options.iter().map(|option| html! {
+                                <option
+                                    value={option.clone()}
+                                    selected={option.as_str() == 
current_hardware}
+                                >
+                                    {option.clone()}
+                                </option>
+                            })}
+                        </select>
+                    </label>
 
-                if !is_recent_view {
-                    <HardwareSelector 
on_hardware_select={props.on_hardware_select.clone()} />
-                    <GitrefSelector
-                        gitrefs={gitref_ctx.state.gitrefs.clone()}
-                        
selected_gitref={gitref_ctx.state.selected_gitref.clone().unwrap_or_default()}
-                        on_gitref_select={props.on_gitref_select.clone()}
-                    />
-                }
+                    <label class="sidebar-facet">
+                        <span class="sidebar-facet-label">{"Version"}</span>
+                        <select class="sidebar-facet-select" 
onchange={on_gitref_change}>
+                            <option value="" 
selected={current_gitref.is_empty()}>
+                                {"All"}
+                            </option>
+                            { for gitref_options.iter().map(|option| html! {
+                                <option
+                                    value={option.clone()}
+                                    selected={option.as_str() == 
current_gitref}
+                                >
+                                    {option.clone()}
+                                </option>
+                            })}
+                        </select>
+                    </label>
+                </div>
 
                 <div class="sidebar-kind-chips">
                     { for KindGroup::all().iter().map(|group| {
@@ -191,11 +269,10 @@ pub fn sidebar(props: &SidebarProps) -> Html {
             </div>
 
             <div class="sidebar-scrollable-content">
-                if is_recent_view {
-                    <RecentBenchmarksSelector limit={10000} />
-                } else {
-                    <BenchmarkSelector />
-                }
+                <BenchmarksList
+                    benchmarks={(*benchmarks).clone()}
+                    is_loading={*is_loading}
+                />
             </div>
         </aside>
     }
@@ -247,3 +324,51 @@ fn render_compare_hint(ui: 
&yew::UseReducerHandle<crate::state::ui::UiState>) ->
 fn short_name(full: &str) -> String {
     full.split('(').next().unwrap_or(full).trim().to_string()
 }
+
+fn collect_hardware(benchmarks: &[BenchmarkReportLight]) -> Vec<String> {
+    let mut set: BTreeSet<String> = BTreeSet::new();
+    for benchmark in benchmarks {
+        if let Some(id) = benchmark.hardware.identifier.as_deref()
+            && !id.is_empty()
+        {
+            set.insert(id.to_string());
+        }
+    }
+    set.into_iter().collect()
+}
+
+fn collect_gitrefs(
+    benchmarks: &[BenchmarkReportLight],
+    hardware_filter: Option<&str>,
+) -> Vec<String> {
+    let mut newest: std::collections::HashMap<String, &BenchmarkReportLight> =
+        std::collections::HashMap::new();
+    for benchmark in benchmarks {
+        if let Some(expected) = hardware_filter
+            && benchmark.hardware.identifier.as_deref() != Some(expected)
+        {
+            continue;
+        }
+        let Some(gitref) = benchmark.params.gitref.as_deref() else {
+            continue;
+        };
+        if gitref.is_empty() {
+            continue;
+        }
+        newest
+            .entry(gitref.to_string())
+            .and_modify(|existing| {
+                if recency_cmp(benchmark, existing).is_gt() {
+                    *existing = benchmark;
+                }
+            })
+            .or_insert(benchmark);
+    }
+
+    let mut ordered: Vec<(&BenchmarkReportLight, String)> = newest
+        .into_iter()
+        .map(|(gitref, benchmark)| (benchmark, gitref))
+        .collect();
+    ordered.sort_by(|left, right| recency_cmp(right.0, left.0));
+    ordered.into_iter().map(|(_, gitref)| gitref).collect()
+}
diff --git a/core/bench/dashboard/frontend/src/components/layout/top_app_bar.rs 
b/core/bench/dashboard/frontend/src/components/layout/top_app_bar.rs
index f5893097f..6b1f28e1e 100644
--- a/core/bench/dashboard/frontend/src/components/layout/top_app_bar.rs
+++ b/core/bench/dashboard/frontend/src/components/layout/top_app_bar.rs
@@ -25,10 +25,8 @@ use 
crate::components::tooltips::server_stats_tooltip::ServerStatsTooltip;
 use crate::router::AppRoute;
 use crate::state::benchmark::{BenchmarkAction, use_benchmark};
 use crate::state::ui::{TopBarPopup, UiAction, use_ui};
-use bench_dashboard_shared::BenchmarkReportLight;
-use bench_report::benchmark_kind::BenchmarkKind;
 use gloo::console::log;
-use std::collections::BTreeMap;
+use gloo::timers::callback::Timeout;
 use yew::platform::spawn_local;
 use yew::prelude::*;
 use yew_router::prelude::{Navigator, use_navigator};
@@ -115,6 +113,26 @@ pub fn top_app_bar(props: &TopAppBarProps) -> Html {
         })
     };
 
+    let share_copied = use_state(|| false);
+    let on_share = {
+        let share_copied = share_copied.clone();
+        Callback::from(move |_| {
+            let Some(window) = web_sys::window() else {
+                return;
+            };
+            let url = window.location().href().unwrap_or_else(|_| 
String::new());
+            if url.is_empty() {
+                return;
+            }
+            let clipboard = window.navigator().clipboard();
+            let _ = clipboard.write_text(&url);
+            share_copied.set(true);
+            let share_copied_for_timer = share_copied.clone();
+            let timeout = Timeout::new(1_400, move || 
share_copied_for_timer.set(false));
+            timeout.forget();
+        })
+    };
+
     let on_embed_toggle = {
         let ui = ui.clone();
         Callback::from(move |_| 
ui.dispatch(UiAction::TogglePopup(TopBarPopup::Embed)))
@@ -132,18 +150,13 @@ pub fn top_app_bar(props: &TopAppBarProps) -> Html {
 
     let on_browse_click = {
         let navigator = navigator.clone();
-        let entries = benchmark_ctx.state.entries.clone();
         Callback::from(move |_| {
-            if let Some(uuid) = latest_uuid_from_entries(&entries) {
-                navigate_to_benchmark(&navigator, uuid);
-            } else {
-                let navigator = navigator.clone();
-                spawn_local(async move {
-                    if let Some(uuid) = fetch_latest_uuid().await {
-                        navigate_to_benchmark(&navigator, uuid);
-                    }
-                });
-            }
+            let navigator = navigator.clone();
+            spawn_local(async move {
+                if let Some(uuid) = fetch_latest_uuid().await {
+                    navigate_to_benchmark(&navigator, uuid);
+                }
+            });
         })
     };
 
@@ -212,6 +225,20 @@ pub fn top_app_bar(props: &TopAppBarProps) -> Html {
                     </button>
                 }
                 if props.show_detail_actions && selected_benchmark.is_some() {
+                    <div class="app-bar-icon-wrap">
+                        <button
+                            type="button"
+                            class={classes!("app-bar-icon-btn", 
(*share_copied).then_some("active"))}
+                            onclick={on_share}
+                            title={if *share_copied { "Link copied" } else { 
"Copy share link" }}
+                            aria-label="Copy share link"
+                        >
+                            { render_share_icon(*share_copied) }
+                        </button>
+                        if *share_copied {
+                            <span class="app-bar-toast" role="status">{"Link 
copied"}</span>
+                        }
+                    </div>
                     <button
                         type="button"
                         class="app-bar-icon-btn"
@@ -252,7 +279,6 @@ pub fn top_app_bar(props: &TopAppBarProps) -> Html {
                             <ServerStatsTooltip
                                 benchmark_report={selected_benchmark.clone()}
                                 visible={true}
-                                view_mode={ui.view_mode.clone()}
                             />
                         }
                     </div>
@@ -267,7 +293,6 @@ pub fn top_app_bar(props: &TopAppBarProps) -> Html {
                             <BenchmarkInfoTooltip
                                 benchmark_report={benchmark.clone()}
                                 visible={true}
-                                view_mode={ui.view_mode.clone()}
                             />
                         }
                     </div>
@@ -354,6 +379,27 @@ fn render_download_icon() -> Html {
     }
 }
 
+fn render_share_icon(copied: bool) -> Html {
+    if copied {
+        return html! {
+            <svg xmlns="http://www.w3.org/2000/svg"; width="18" height="18" 
viewBox="0 0 24 24"
+                 fill="none" stroke="currentColor" stroke-width="2.3" 
stroke-linecap="round" stroke-linejoin="round">
+                <polyline points="20 6 9 17 4 12" />
+            </svg>
+        };
+    }
+    html! {
+        <svg xmlns="http://www.w3.org/2000/svg"; width="18" height="18" 
viewBox="0 0 24 24"
+             fill="none" stroke="currentColor" stroke-width="2" 
stroke-linecap="round" stroke-linejoin="round">
+            <circle cx="18" cy="5" r="3" />
+            <circle cx="6" cy="12" r="3" />
+            <circle cx="18" cy="19" r="3" />
+            <line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
+            <line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
+        </svg>
+    }
+}
+
 fn render_embed_icon() -> Html {
     html! {
         <svg xmlns="http://www.w3.org/2000/svg"; width="18" height="18" 
viewBox="0 0 24 24"
@@ -364,16 +410,6 @@ fn render_embed_icon() -> Html {
     }
 }
 
-fn latest_uuid_from_entries(
-    entries: &BTreeMap<BenchmarkKind, Vec<BenchmarkReportLight>>,
-) -> Option<String> {
-    entries
-        .values()
-        .flatten()
-        .max_by(|left, right| left.timestamp.cmp(&right.timestamp))
-        .map(|benchmark| benchmark.uuid.to_string())
-}
-
 async fn fetch_latest_uuid() -> Option<String> {
     match api::fetch_recent_benchmarks(Some(1)).await {
         Ok(recent) => recent.into_iter().next().map(|b| b.uuid.to_string()),
diff --git 
a/core/bench/dashboard/frontend/src/components/selectors/benchmark_selector.rs 
b/core/bench/dashboard/frontend/src/components/selectors/benchmarks_list.rs
similarity index 73%
rename from 
core/bench/dashboard/frontend/src/components/selectors/benchmark_selector.rs
rename to 
core/bench/dashboard/frontend/src/components/selectors/benchmarks_list.rs
index 54f15d4ee..84a9c625f 100644
--- 
a/core/bench/dashboard/frontend/src/components/selectors/benchmark_selector.rs
+++ b/core/bench/dashboard/frontend/src/components/selectors/benchmarks_list.rs
@@ -18,21 +18,22 @@
 use crate::components::selectors::dense_benchmark_row::DenseBenchmarkRow;
 use crate::format::nan_safe_cmp;
 use crate::router::AppRoute;
-use crate::state::benchmark::{BenchmarkAction, use_benchmark};
+use crate::state::benchmark::{BenchmarkAction, recency_cmp, use_benchmark};
 use crate::state::ui::{KindGroup, SidebarSort, UiAction, use_ui};
 use bench_dashboard_shared::BenchmarkReportLight;
 use bench_report::benchmark_kind::BenchmarkKind;
-use chrono::DateTime;
-use std::cmp::Ordering;
-use std::collections::{BTreeMap, HashSet};
+use std::collections::HashSet;
 use yew::prelude::*;
-use yew_router::prelude::use_navigator;
+use yew_router::prelude::{Navigator, use_navigator};
 
-#[derive(Properties, PartialEq, Default)]
-pub struct BenchmarkSelectorProps;
+#[derive(Properties, PartialEq)]
+pub struct BenchmarksListProps {
+    pub benchmarks: Vec<BenchmarkReportLight>,
+    pub is_loading: bool,
+}
 
-#[function_component(BenchmarkSelector)]
-pub fn benchmark_selector(_props: &BenchmarkSelectorProps) -> Html {
+#[function_component(BenchmarksList)]
+pub fn benchmarks_list(props: &BenchmarksListProps) -> Html {
     let benchmark_ctx = use_benchmark();
     let ui_state = use_ui();
     let navigator = use_navigator();
@@ -44,24 +45,13 @@ pub fn benchmark_selector(_props: &BenchmarkSelectorProps) 
-> Html {
         .as_ref()
         .map(|selected| selected.uuid);
 
-    let filters = ui_state.param_filters.clone();
+    let param_filters = ui_state.param_filters.clone();
     let search = ui_state.sidebar_search.to_lowercase();
     let kind_filter = ui_state.sidebar_kind_filter.clone();
+    let hardware_filter = ui_state.hardware_filter.clone();
+    let gitref_filter = ui_state.gitref_filter.clone();
     let sort = ui_state.sidebar_sort;
 
-    let visible: Vec<BenchmarkReportLight> = benchmark_ctx
-        .state
-        .entries
-        .values()
-        .flatten()
-        .filter(|benchmark| filters.matches(benchmark))
-        .filter(|benchmark| kind_filter_matches(&kind_filter, 
benchmark.params.benchmark_kind))
-        .filter(|benchmark| search_matches(&search, benchmark))
-        .cloned()
-        .collect();
-    let hidden_by_filter = total_benchmarks(&benchmark_ctx.state.entries) - 
visible.len();
-    let sorted = sort_benchmarks(visible, sort);
-
     let on_select = {
         let dispatch = benchmark_ctx.dispatch.clone();
         let navigator = navigator.clone();
@@ -95,7 +85,7 @@ pub fn benchmark_selector(_props: &BenchmarkSelectorProps) -> 
Html {
                 && pinned == &clicked_uuid
                 && let Some(selected) = selected_uuid.as_ref()
             {
-                navigate(
+                push_route(
                     &navigator,
                     AppRoute::Benchmark {
                         uuid: selected.clone(),
@@ -107,7 +97,7 @@ pub fn benchmark_selector(_props: &BenchmarkSelectorProps) 
-> Html {
             if let Some(selected) = selected_uuid
                 && selected != clicked_uuid
             {
-                navigate(
+                push_route(
                     &navigator,
                     AppRoute::Compare {
                         left: selected,
@@ -124,18 +114,31 @@ pub fn benchmark_selector(_props: 
&BenchmarkSelectorProps) -> Html {
         })
     };
 
-    if sorted.is_empty() {
+    if props.is_loading {
+        return render_skeleton();
+    }
+
+    let visible: Vec<BenchmarkReportLight> = props
+        .benchmarks
+        .iter()
+        .filter(|benchmark| param_filters.matches(benchmark))
+        .filter(|benchmark| kind_filter_matches(&kind_filter, 
benchmark.params.benchmark_kind))
+        .filter(|benchmark| hardware_matches(hardware_filter.as_deref(), 
benchmark))
+        .filter(|benchmark| gitref_matches(gitref_filter.as_deref(), 
benchmark))
+        .filter(|benchmark| search_matches(&search, benchmark))
+        .cloned()
+        .collect();
+
+    if visible.is_empty() {
         return html! {
             <div class="dense-list-empty">
-                if hidden_by_filter > 0 {
-                    <p>{format!("{hidden_by_filter} benchmark(s) hidden. 
Adjust filters or search.")}</p>
-                } else {
-                    <p>{"No benchmarks for this gitref yet."}</p>
-                }
+                <p>{"No benchmarks match the current filters."}</p>
             </div>
         };
     }
 
+    let sorted = sort_benchmarks(visible, sort);
+
     html! {
         <div class="dense-list">
             { for sorted.iter().map(|benchmark| html! {
@@ -145,19 +148,35 @@ pub fn benchmark_selector(_props: 
&BenchmarkSelectorProps) -> Html {
                     pinned_uuid={pinned_uuid}
                     on_select={on_select.clone()}
                     on_toggle_pin={on_toggle_pin.clone()}
-                    show_timestamp={false}
+                    show_timestamp={true}
                 />
             })}
         </div>
     }
 }
 
-fn navigate(navigator: &Option<yew_router::prelude::Navigator>, route: 
AppRoute) {
+fn push_route(navigator: &Option<Navigator>, route: AppRoute) {
     if let Some(nav) = navigator.as_ref() {
         nav.push(&route);
     }
 }
 
+fn render_skeleton() -> Html {
+    html! {
+        <div class="dense-list">
+            { for (0..5).map(|index| html! {
+                <div class="dense-row-skeleton" style={format!("--stagger: 
{index}")}>
+                    <span class="skeleton-dot" />
+                    <div class="skeleton-body">
+                        <span class="skeleton-line title" />
+                        <span class="skeleton-line meta" />
+                    </div>
+                </div>
+            })}
+        </div>
+    }
+}
+
 fn kind_filter_matches(filter: &HashSet<KindGroup>, kind: BenchmarkKind) -> 
bool {
     if filter.is_empty() {
         return true;
@@ -165,6 +184,20 @@ fn kind_filter_matches(filter: &HashSet<KindGroup>, kind: 
BenchmarkKind) -> bool
     filter.iter().any(|group| group.matches(kind))
 }
 
+fn hardware_matches(filter: Option<&str>, benchmark: &BenchmarkReportLight) -> 
bool {
+    match filter {
+        Some(expected) => benchmark.hardware.identifier.as_deref() == 
Some(expected),
+        None => true,
+    }
+}
+
+fn gitref_matches(filter: Option<&str>, benchmark: &BenchmarkReportLight) -> 
bool {
+    match filter {
+        Some(expected) => benchmark.params.gitref.as_deref() == Some(expected),
+        None => true,
+    }
+}
+
 fn search_matches(query: &str, benchmark: &BenchmarkReportLight) -> bool {
     if query.is_empty() {
         return true;
@@ -191,19 +224,18 @@ fn search_matches(query: &str, benchmark: 
&BenchmarkReportLight) -> bool {
     {
         return true;
     }
+    if benchmark.timestamp.to_lowercase().contains(query) {
+        return true;
+    }
     false
 }
 
-fn total_benchmarks(entries: &BTreeMap<BenchmarkKind, 
Vec<BenchmarkReportLight>>) -> usize {
-    entries.values().map(|values| values.len()).sum()
-}
-
 fn sort_benchmarks(
     mut benchmarks: Vec<BenchmarkReportLight>,
     sort: SidebarSort,
 ) -> Vec<BenchmarkReportLight> {
     benchmarks.sort_by(|left, right| match sort {
-        SidebarSort::MostRecent => compare_timestamps(&right.timestamp, 
&left.timestamp),
+        SidebarSort::MostRecent => recency_cmp(right, left),
         SidebarSort::PeakThroughput => nan_safe_cmp(throughput(right), 
throughput(left)),
         SidebarSort::LowestP99 => nan_safe_cmp(p99(left), p99(right)),
         SidebarSort::Name => 
left.params.pretty_name.cmp(&right.params.pretty_name),
@@ -211,16 +243,6 @@ fn sort_benchmarks(
     benchmarks
 }
 
-fn compare_timestamps(left: &str, right: &str) -> Ordering {
-    match (
-        DateTime::parse_from_rfc3339(left),
-        DateTime::parse_from_rfc3339(right),
-    ) {
-        (Ok(left_time), Ok(right_time)) => left_time.cmp(&right_time),
-        _ => Ordering::Equal,
-    }
-}
-
 fn throughput(benchmark: &BenchmarkReportLight) -> f64 {
     benchmark
         .group_metrics
diff --git 
a/core/bench/dashboard/frontend/src/components/selectors/gitref_selector.rs 
b/core/bench/dashboard/frontend/src/components/selectors/gitref_selector.rs
deleted file mode 100644
index 440f2e5b3..000000000
--- a/core/bench/dashboard/frontend/src/components/selectors/gitref_selector.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use wasm_bindgen::JsCast;
-use web_sys::HtmlSelectElement;
-use yew::prelude::*;
-
-#[derive(Properties, PartialEq)]
-pub struct GitrefSelectorProps {
-    pub gitrefs: Vec<String>,
-    pub selected_gitref: String,
-    pub on_gitref_select: Callback<String>,
-}
-
-#[function_component(GitrefSelector)]
-pub fn gitref_selector(props: &GitrefSelectorProps) -> Html {
-    let onchange = {
-        let on_gitref_select = props.on_gitref_select.clone();
-        Callback::from(move |e: Event| {
-            if let Some(select) = e
-                .target()
-                .and_then(|t| t.dyn_into::<HtmlSelectElement>().ok())
-            {
-                let gitref = select.value();
-                on_gitref_select.emit(gitref);
-            }
-        })
-    };
-
-    html! {
-        <div class="gitref-select">
-            <h3>{"Version"}</h3>
-            <select {onchange} value={props.selected_gitref.clone()}>
-                {
-                    props.gitrefs.iter().map(|gitref| {
-                        html! {
-                            <option
-                                value={gitref.clone()}
-                                selected={gitref == &props.selected_gitref}
-                            >
-                                {gitref}
-                            </option>
-                        }
-                    }).collect::<Html>()
-                }
-            </select>
-        </div>
-    }
-}
diff --git 
a/core/bench/dashboard/frontend/src/components/selectors/hardware_selector.rs 
b/core/bench/dashboard/frontend/src/components/selectors/hardware_selector.rs
deleted file mode 100644
index fc2a9eb4a..000000000
--- 
a/core/bench/dashboard/frontend/src/components/selectors/hardware_selector.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use crate::state::hardware::use_hardware;
-use gloo::console::log;
-use yew::prelude::*;
-
-#[derive(Properties, PartialEq)]
-pub struct HardwareSelectorProps {
-    pub on_hardware_select: Callback<String>,
-}
-
-#[function_component(HardwareSelector)]
-pub fn hardware_selector(props: &HardwareSelectorProps) -> Html {
-    let hardware_ctx = use_hardware();
-
-    let on_hardware_change = 
create_on_hardware_change_callback(props.on_hardware_select.clone());
-
-    html! {
-        <div class="hardware-selector">
-            <h3>{"Hardware"}</h3>
-            <select
-                onchange={on_hardware_change.clone()}
-            >
-                { for hardware_ctx.state.hardware_list.iter().map(|hardware| 
html! {
-                    <option
-                        value={hardware.identifier.clone().unwrap_or_else(|| 
"Unknown".to_string())}
-                        selected={hardware_ctx.state.selected_hardware == 
Some(hardware.identifier.clone().unwrap_or_else(|| "Unknown".to_string()))}
-                    >
-                        {format!("{} @ {}", 
hardware.identifier.clone().unwrap_or_else(|| "Unknown".to_string()), 
&hardware.cpu_name)}
-                    </option>
-                }) }
-            </select>
-        </div>
-    }
-}
-
-fn create_on_hardware_change_callback(on_hardware_select: Callback<String>) -> 
Callback<Event> {
-    Callback::from(move |e: Event| {
-        let target = e.target_dyn_into::<web_sys::HtmlSelectElement>();
-        if let Some(select) = target {
-            let value = select.value();
-            log!(format!("Hardware selected via dropdown: {}", value));
-            on_hardware_select.emit(value);
-        }
-    })
-}
diff --git a/core/bench/dashboard/frontend/src/components/selectors/mod.rs 
b/core/bench/dashboard/frontend/src/components/selectors/mod.rs
index 7c0bdef59..6eebff182 100644
--- a/core/bench/dashboard/frontend/src/components/selectors/mod.rs
+++ b/core/bench/dashboard/frontend/src/components/selectors/mod.rs
@@ -15,10 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-pub mod benchmark_selector;
+pub mod benchmarks_list;
 pub mod dense_benchmark_row;
-pub mod gitref_selector;
-pub mod hardware_selector;
 pub mod measurement_type_selector;
 pub mod param_filters_panel;
-pub mod recent_benchmarks_selector;
diff --git 
a/core/bench/dashboard/frontend/src/components/selectors/recent_benchmarks_selector.rs
 
b/core/bench/dashboard/frontend/src/components/selectors/recent_benchmarks_selector.rs
deleted file mode 100644
index 0c06ee5ab..000000000
--- 
a/core/bench/dashboard/frontend/src/components/selectors/recent_benchmarks_selector.rs
+++ /dev/null
@@ -1,302 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use crate::api;
-use crate::components::selectors::dense_benchmark_row::DenseBenchmarkRow;
-use crate::format::nan_safe_cmp;
-use crate::router::AppRoute;
-use crate::state::benchmark::{BenchmarkAction, use_benchmark};
-use crate::state::ui::{KindGroup, SidebarSort, UiAction, use_ui};
-use bench_dashboard_shared::BenchmarkReportLight;
-use bench_report::benchmark_kind::BenchmarkKind;
-use chrono::DateTime;
-use gloo::console::log;
-use std::cell::Cell;
-use std::cmp::Ordering;
-use std::collections::HashSet;
-use std::rc::Rc;
-use yew::platform::spawn_local;
-use yew::prelude::*;
-use yew_router::prelude::{Navigator, use_navigator};
-
-#[derive(Properties, PartialEq)]
-pub struct RecentBenchmarksSelectorProps {
-    pub limit: u32,
-}
-
-#[function_component(RecentBenchmarksSelector)]
-pub fn recent_benchmarks_selector(props: &RecentBenchmarksSelectorProps) -> 
Html {
-    let benchmark_ctx = use_benchmark();
-    let ui_state = use_ui();
-    let navigator = use_navigator();
-
-    let pinned_uuid = ui_state.compare_pin.as_ref().map(|pin| pin.uuid);
-    let selected_uuid = benchmark_ctx
-        .state
-        .selected_benchmark
-        .as_ref()
-        .map(|selected| selected.uuid);
-
-    let filters = ui_state.param_filters.clone();
-    let search = ui_state.sidebar_search.to_lowercase();
-    let kind_filter = ui_state.sidebar_kind_filter.clone();
-    let sort = ui_state.sidebar_sort;
-
-    let recent_benchmarks = use_state(Vec::<BenchmarkReportLight>::new);
-    let is_loading = use_state(|| true);
-
-    {
-        let recent_benchmarks = recent_benchmarks.clone();
-        let is_loading = is_loading.clone();
-        let limit = props.limit;
-        let dispatch = benchmark_ctx.dispatch.clone();
-        let navigator = navigator.clone();
-        let has_selection = benchmark_ctx.state.selected_benchmark.is_some();
-
-        let cancelled = Rc::new(Cell::new(false));
-        let cancelled_async = cancelled.clone();
-        use_effect_with((), move |_| {
-            spawn_local(async move {
-                match api::fetch_recent_benchmarks(Some(limit)).await {
-                    Ok(mut data) => {
-                        data.sort_by(|left, right| {
-                            compare_timestamps(&right.timestamp, 
&left.timestamp)
-                        });
-                        if cancelled_async.get() {
-                            return;
-                        }
-                        if !has_selection && let Some(most_recent) = 
data.first().cloned() {
-                            if let Some(nav) = navigator.as_ref() {
-                                nav.push(&AppRoute::Benchmark {
-                                    uuid: most_recent.uuid.to_string(),
-                                });
-                            }
-                            
dispatch.emit(BenchmarkAction::SelectBenchmark(Box::new(Some(
-                                most_recent,
-                            ))));
-                        }
-                        recent_benchmarks.set(data);
-                    }
-                    Err(error) => log!(format!("Error fetching recent 
benchmarks: {}", error)),
-                }
-                if !cancelled_async.get() {
-                    is_loading.set(false);
-                }
-            });
-            move || cancelled.set(true)
-        });
-    }
-
-    let on_select = {
-        let dispatch = benchmark_ctx.dispatch.clone();
-        let navigator = navigator.clone();
-        Callback::from(move |benchmark: BenchmarkReportLight| {
-            if let Some(nav) = navigator.as_ref() {
-                nav.push(&AppRoute::Benchmark {
-                    uuid: benchmark.uuid.to_string(),
-                });
-            }
-            
dispatch.emit(BenchmarkAction::SelectBenchmark(Box::new(Some(benchmark))));
-        })
-    };
-
-    let on_toggle_pin = {
-        let ui_state = ui_state.clone();
-        let navigator = navigator.clone();
-        let benchmark_ctx = benchmark_ctx.clone();
-        Callback::from(move |benchmark: BenchmarkReportLight| {
-            let clicked_uuid = benchmark.uuid.to_string();
-            let selected_uuid = benchmark_ctx
-                .state
-                .selected_benchmark
-                .as_ref()
-                .map(|selected| selected.uuid.to_string());
-            let pinned_uuid = ui_state
-                .compare_pin
-                .as_ref()
-                .map(|pin| pin.uuid.to_string());
-
-            if let Some(pinned) = pinned_uuid.as_ref()
-                && pinned == &clicked_uuid
-                && let Some(selected) = selected_uuid.as_ref()
-            {
-                push_route(
-                    &navigator,
-                    AppRoute::Benchmark {
-                        uuid: selected.clone(),
-                    },
-                );
-                return;
-            }
-
-            if let Some(selected) = selected_uuid
-                && selected != clicked_uuid
-            {
-                push_route(
-                    &navigator,
-                    AppRoute::Compare {
-                        left: selected,
-                        right: clicked_uuid,
-                    },
-                );
-                return;
-            }
-
-            let same_pin =
-                ui_state.compare_pin.as_ref().map(|pin| pin.uuid) == 
Some(benchmark.uuid);
-            let next = if same_pin { None } else { Some(benchmark) };
-            ui_state.dispatch(UiAction::SetComparePin(Box::new(next)));
-        })
-    };
-
-    if *is_loading {
-        return render_skeleton();
-    }
-
-    let visible: Vec<BenchmarkReportLight> = (*recent_benchmarks)
-        .iter()
-        .filter(|benchmark| filters.matches(benchmark))
-        .filter(|benchmark| kind_filter_matches(&kind_filter, 
benchmark.params.benchmark_kind))
-        .filter(|benchmark| search_matches(&search, benchmark))
-        .cloned()
-        .collect();
-
-    if visible.is_empty() {
-        return html! {
-            <div class="dense-list-empty">
-                <p>{"No benchmarks match the current search or filters."}</p>
-            </div>
-        };
-    }
-
-    let sorted = sort_benchmarks(visible, sort);
-
-    html! {
-        <div class="dense-list">
-            { for sorted.iter().map(|benchmark| html! {
-                <DenseBenchmarkRow
-                    benchmark={benchmark.clone()}
-                    selected_uuid={selected_uuid}
-                    pinned_uuid={pinned_uuid}
-                    on_select={on_select.clone()}
-                    on_toggle_pin={on_toggle_pin.clone()}
-                    show_timestamp={true}
-                />
-            })}
-        </div>
-    }
-}
-
-fn push_route(navigator: &Option<Navigator>, route: AppRoute) {
-    if let Some(nav) = navigator.as_ref() {
-        nav.push(&route);
-    }
-}
-
-fn render_skeleton() -> Html {
-    html! {
-        <div class="dense-list">
-            { for (0..5).map(|index| html! {
-                <div class="dense-row-skeleton" style={format!("--stagger: 
{index}")}>
-                    <span class="skeleton-dot" />
-                    <div class="skeleton-body">
-                        <span class="skeleton-line title" />
-                        <span class="skeleton-line meta" />
-                    </div>
-                </div>
-            })}
-        </div>
-    }
-}
-
-fn kind_filter_matches(filter: &HashSet<KindGroup>, kind: BenchmarkKind) -> 
bool {
-    if filter.is_empty() {
-        return true;
-    }
-    filter.iter().any(|group| group.matches(kind))
-}
-
-fn search_matches(query: &str, benchmark: &BenchmarkReportLight) -> bool {
-    if query.is_empty() {
-        return true;
-    }
-    let kind_label = 
benchmark.params.benchmark_kind.to_string().to_lowercase();
-    if kind_label.contains(query) {
-        return true;
-    }
-    if benchmark.params.pretty_name.to_lowercase().contains(query) {
-        return true;
-    }
-    if let Some(remark) = benchmark.params.remark.as_deref()
-        && remark.to_lowercase().contains(query)
-    {
-        return true;
-    }
-    if let Some(gitref) = benchmark.params.gitref.as_deref()
-        && gitref.to_lowercase().contains(query)
-    {
-        return true;
-    }
-    if let Some(hardware) = benchmark.hardware.identifier.as_deref()
-        && hardware.to_lowercase().contains(query)
-    {
-        return true;
-    }
-    if benchmark.timestamp.to_lowercase().contains(query) {
-        return true;
-    }
-    false
-}
-
-fn sort_benchmarks(
-    mut benchmarks: Vec<BenchmarkReportLight>,
-    sort: SidebarSort,
-) -> Vec<BenchmarkReportLight> {
-    benchmarks.sort_by(|left, right| match sort {
-        SidebarSort::MostRecent => compare_timestamps(&right.timestamp, 
&left.timestamp),
-        SidebarSort::PeakThroughput => nan_safe_cmp(throughput(right), 
throughput(left)),
-        SidebarSort::LowestP99 => nan_safe_cmp(p99(left), p99(right)),
-        SidebarSort::Name => 
left.params.pretty_name.cmp(&right.params.pretty_name),
-    });
-    benchmarks
-}
-
-fn compare_timestamps(left: &str, right: &str) -> Ordering {
-    match (
-        DateTime::parse_from_rfc3339(left),
-        DateTime::parse_from_rfc3339(right),
-    ) {
-        (Ok(left_time), Ok(right_time)) => left_time.cmp(&right_time),
-        _ => Ordering::Equal,
-    }
-}
-
-fn throughput(benchmark: &BenchmarkReportLight) -> f64 {
-    benchmark
-        .group_metrics
-        .first()
-        .map(|metrics| metrics.summary.total_throughput_megabytes_per_second)
-        .unwrap_or(0.0)
-}
-
-fn p99(benchmark: &BenchmarkReportLight) -> f64 {
-    benchmark
-        .group_metrics
-        .first()
-        .map(|metrics| metrics.summary.average_p99_latency_ms)
-        .unwrap_or(f64::INFINITY)
-}
diff --git 
a/core/bench/dashboard/frontend/src/components/tooltips/benchmark_info_tooltip.rs
 
b/core/bench/dashboard/frontend/src/components/tooltips/benchmark_info_tooltip.rs
index 255e71442..d56e06bb1 100644
--- 
a/core/bench/dashboard/frontend/src/components/tooltips/benchmark_info_tooltip.rs
+++ 
b/core/bench/dashboard/frontend/src/components/tooltips/benchmark_info_tooltip.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::state::ui::ViewMode;
 use bench_dashboard_shared::BenchmarkReportLight;
 use gloo::timers::callback::Timeout;
 use web_sys::window;
@@ -25,7 +24,6 @@ use yew::prelude::*;
 pub struct BenchmarkInfoTooltipProps {
     pub benchmark_report: Option<BenchmarkReportLight>,
     pub visible: bool,
-    pub view_mode: ViewMode,
 }
 
 #[function_component(BenchmarkInfoTooltip)]
@@ -37,7 +35,6 @@ pub fn benchmark_info_tooltip(props: 
&BenchmarkInfoTooltipProps) -> Html {
     let benchmark_report = props.benchmark_report.as_ref().unwrap();
     let hardware = &benchmark_report.hardware;
     let params = &benchmark_report.params;
-    let is_trend_view = matches!(props.view_mode, ViewMode::GitrefTrend);
     let notification_visible = use_state(|| false);
 
     let onclick = {
@@ -73,13 +70,7 @@ pub fn benchmark_info_tooltip(props: 
&BenchmarkInfoTooltipProps) -> Html {
             <div class="tooltip-section">
                 <h4>{"Benchmark Parameters"}</h4>
                 <div class="tooltip-content">
-                    {if !is_trend_view {
-                        html! {
-                            <p><strong>{"Time: 
"}</strong>{&benchmark_report.timestamp}</p>
-                        }
-                    } else {
-                        html! {}
-                    }}
+                    <p><strong>{"Time: 
"}</strong>{&benchmark_report.timestamp}</p>
                     <p><strong>{"Kind: "}</strong>{&params.benchmark_kind}</p>
                     <p><strong>{"Transport: "}</strong>{&params.transport}</p>
                     <p><strong>{"Messages: "}</strong>{format!("{} x {} ({} 
bytes)",
@@ -101,16 +92,8 @@ pub fn benchmark_info_tooltip(props: 
&BenchmarkInfoTooltipProps) -> Html {
                             )
                         }
                     }</p>
-                    {if !is_trend_view {
-                        html! {
-                            <>
-                                <p><strong>{"Git ref: 
"}</strong>{params.gitref.clone()}</p>
-                                <p><strong>{"Git ref date: 
"}</strong>{params.gitref_date.clone()}</p>
-                            </>
-                        }
-                    } else {
-                        html! {}
-                    }}
+                    <p><strong>{"Git ref: 
"}</strong>{params.gitref.clone()}</p>
+                    <p><strong>{"Git ref date: 
"}</strong>{params.gitref_date.clone()}</p>
                 </div>
             </div>
             <div class="tooltip-section">
diff --git 
a/core/bench/dashboard/frontend/src/components/tooltips/server_stats_tooltip.rs 
b/core/bench/dashboard/frontend/src/components/tooltips/server_stats_tooltip.rs
index 878d8ca19..20587c555 100644
--- 
a/core/bench/dashboard/frontend/src/components/tooltips/server_stats_tooltip.rs
+++ 
b/core/bench/dashboard/frontend/src/components/tooltips/server_stats_tooltip.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::state::ui::ViewMode;
 use bench_dashboard_shared::BenchmarkReportLight;
 use yew::prelude::*;
 
@@ -23,7 +22,6 @@ use yew::prelude::*;
 pub struct ServerStatsTooltipProps {
     pub benchmark_report: Option<BenchmarkReportLight>,
     pub visible: bool,
-    pub view_mode: ViewMode,
 }
 
 #[function_component(ServerStatsTooltip)]
diff --git a/core/bench/dashboard/frontend/src/main.rs 
b/core/bench/dashboard/frontend/src/main.rs
index fa5479fc8..f36373842 100644
--- a/core/bench/dashboard/frontend/src/main.rs
+++ b/core/bench/dashboard/frontend/src/main.rs
@@ -23,6 +23,7 @@ mod format;
 mod hooks;
 mod router;
 mod state;
+mod version;
 
 use crate::{
     components::{app_content::AppContent, footer::Footer},
diff --git a/core/bench/dashboard/frontend/src/state/benchmark.rs 
b/core/bench/dashboard/frontend/src/state/benchmark.rs
index 216715c64..4838b4979 100644
--- a/core/bench/dashboard/frontend/src/state/benchmark.rs
+++ b/core/bench/dashboard/frontend/src/state/benchmark.rs
@@ -16,10 +16,12 @@
 // under the License.
 
 use crate::format::{finite_or, nan_safe_cmp};
+use crate::version::{SemverRecency, parse_semver_recency};
 use bench_dashboard_shared::BenchmarkReportLight;
 use bench_report::benchmark_kind::BenchmarkKind;
-use chrono::{DateTime, Duration};
+use chrono::DateTime;
 use gloo::console::log;
+use std::cmp::Ordering;
 use std::collections::BTreeMap;
 use std::rc::Rc;
 use yew::prelude::*;
@@ -258,42 +260,117 @@ impl BenchmarkState {
     }
 }
 
-/// From a set of benchmarks, pick the one that best represents "current peak":
-/// restrict to runs within 2h of the latest timestamp (avoids UTC day-split 
artifacts
-/// on overnight benchmark sweeps), then pick lowest P99 latency; ties broken 
by
-/// highest total throughput.
+/// Pick the best benchmark from the most recent sweep.
+///
+/// "Sweep" = runs sharing the newest (hardware, gitref). Ranked by lowest P99,
+/// then P99.9, then P99.99, then highest total throughput.
+/// NaN values rank worst so corrupt runs never win.
 pub fn pick_best_from_recent_batch(
     benchmarks: &[&BenchmarkReportLight],
 ) -> Option<BenchmarkReportLight> {
-    let latest_timestamp = benchmarks
-        .iter()
-        .filter_map(|benchmark| 
DateTime::parse_from_rfc3339(&benchmark.timestamp).ok())
-        .max()?;
-    let window_start = latest_timestamp - Duration::hours(2);
+    let mut sweep = latest_sweep(benchmarks);
+    sweep.sort_by_key(rank_sweep_candidate);
+    sweep.first().map(|report| (*report).clone())
+}
 
+pub fn latest_sweep<'a>(benchmarks: &[&'a BenchmarkReportLight]) -> Vec<&'a 
BenchmarkReportLight> {
+    let Some(newest) = benchmarks
+        .iter()
+        .copied()
+        .max_by(|left, right| recency_cmp(left, right))
+    else {
+        return Vec::new();
+    };
+    let sweep_key = sweep_key_of(newest);
     benchmarks
         .iter()
         .copied()
-        .filter(|benchmark| {
-            DateTime::parse_from_rfc3339(&benchmark.timestamp)
-                .map(|timestamp| timestamp >= window_start)
-                .unwrap_or(false)
-        })
-        .min_by(|left, right| {
-            let metrics = |report: &BenchmarkReportLight| {
-                report.group_metrics.first().map(|group| {
-                    (
-                        finite_or(group.summary.average_p99_latency_ms, 
f64::INFINITY),
-                        
finite_or(group.summary.total_throughput_megabytes_per_second, 0.0),
-                    )
-                })
-            };
-            let (left_p99, left_throughput) = 
metrics(left).unwrap_or((f64::INFINITY, 0.0));
-            let (right_p99, right_throughput) = 
metrics(right).unwrap_or((f64::INFINITY, 0.0));
-            nan_safe_cmp(left_p99, right_p99)
-                .then_with(|| nan_safe_cmp(right_throughput, left_throughput))
-        })
-        .cloned()
+        .filter(|benchmark| sweep_key_of(benchmark) == sweep_key)
+        .collect()
+}
+
+/// Order benchmarks by "most recent" using semver-aware recency.
+///
+/// Benchmarks whose gitref parses as a semver-like tag (e.g. `0.7.0`,
+/// `0.7.0-edge.1`) are newer than any plain-commit run. Within each
+/// group we tie-break on RFC3339 timestamp so rebuilds of the same
+/// gitref still order by wall clock.
+pub fn recency_cmp(left: &BenchmarkReportLight, right: &BenchmarkReportLight) 
-> Ordering {
+    let left_semver = 
left.params.gitref.as_deref().and_then(parse_semver_recency);
+    let right_semver = right
+        .params
+        .gitref
+        .as_deref()
+        .and_then(parse_semver_recency);
+    compare_semver_group(left_semver.as_ref(), right_semver.as_ref())
+        .then_with(|| timestamp_cmp(&left.timestamp, &right.timestamp))
+}
+
+fn compare_semver_group(left: Option<&SemverRecency>, right: 
Option<&SemverRecency>) -> Ordering {
+    match (left, right) {
+        (Some(l), Some(r)) => l.cmp(r),
+        (Some(_), None) => Ordering::Greater,
+        (None, Some(_)) => Ordering::Less,
+        (None, None) => Ordering::Equal,
+    }
+}
+
+fn timestamp_cmp(left: &str, right: &str) -> Ordering {
+    match (
+        DateTime::parse_from_rfc3339(left),
+        DateTime::parse_from_rfc3339(right),
+    ) {
+        (Ok(l), Ok(r)) => l.cmp(&r),
+        _ => Ordering::Equal,
+    }
+}
+
+fn sweep_key_of(benchmark: &BenchmarkReportLight) -> (Option<String>, 
Option<String>) {
+    (
+        benchmark.hardware.identifier.clone(),
+        benchmark.params.gitref.clone(),
+    )
+}
+
+fn rank_sweep_candidate(
+    benchmark: &&BenchmarkReportLight,
+) -> (FloatKey, FloatKey, FloatKey, FloatKey) {
+    let summary = benchmark.group_metrics.first().map(|group| &group.summary);
+    let p99 = summary
+        .map(|summary| finite_or(summary.average_p99_latency_ms, 
f64::INFINITY))
+        .unwrap_or(f64::INFINITY);
+    let p999 = summary
+        .map(|summary| finite_or(summary.average_p999_latency_ms, 
f64::INFINITY))
+        .unwrap_or(f64::INFINITY);
+    let p9999 = summary
+        .map(|summary| finite_or(summary.average_p9999_latency_ms, 
f64::INFINITY))
+        .unwrap_or(f64::INFINITY);
+    let throughput = summary
+        .map(|summary| 
finite_or(summary.total_throughput_megabytes_per_second, 0.0))
+        .unwrap_or(0.0);
+    (
+        FloatKey(p99),
+        FloatKey(p999),
+        FloatKey(p9999),
+        FloatKey(-throughput),
+    )
+}
+
+#[derive(Clone, Copy, PartialEq)]
+struct FloatKey(f64);
+
+impl Eq for FloatKey {}
+
+impl Ord for FloatKey {
+    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+        nan_safe_cmp(self.0, other.0)
+    }
+}
+
+impl PartialOrd for FloatKey {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        Some(self.cmp(other))
+    }
 }
 
 #[derive(Debug)]
@@ -356,54 +433,281 @@ mod tests {
     }
 
     #[test]
-    fn given_runs_within_window_when_picking_should_return_lowest_p99() {
-        let a = benchmark("2026-04-21T10:00:00Z", 5.0, 100.0);
-        let b = benchmark("2026-04-21T10:30:00Z", 2.0, 80.0);
-        let c = benchmark("2026-04-21T11:00:00Z", 3.5, 120.0);
+    fn given_sweep_runs_when_picking_should_return_lowest_p99() {
+        let a = run(
+            "2026-04-21T10:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [5.0, 10.0, 20.0],
+            100.0,
+        );
+        let b = run(
+            "2026-04-21T10:30:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 8.0, 18.0],
+            80.0,
+        );
+        let c = run(
+            "2026-04-21T11:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [3.5, 9.0, 19.0],
+            120.0,
+        );
         let picked = pick_best_from_recent_batch(&[&a, &b, 
&c]).expect("expected a pick");
         assert_eq!(picked.timestamp, b.timestamp);
     }
 
     #[test]
-    fn given_tie_on_p99_when_picking_should_break_tie_on_throughput() {
-        let low_tput = benchmark("2026-04-21T10:00:00Z", 2.0, 100.0);
-        let high_tput = benchmark("2026-04-21T10:10:00Z", 2.0, 200.0);
-        let picked = pick_best_from_recent_batch(&[&low_tput, 
&high_tput]).expect("expected pick");
+    fn given_tie_on_p99_when_picking_should_break_on_p999() {
+        let worse_tail = run(
+            "2026-04-21T10:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 20.0, 30.0],
+            500.0,
+        );
+        let better_tail = run(
+            "2026-04-21T10:10:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 12.0, 30.0],
+            90.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&worse_tail, 
&better_tail]).expect("pick");
+        assert_eq!(picked.timestamp, better_tail.timestamp);
+    }
+
+    #[test]
+    fn given_tie_on_p99_and_p999_when_picking_should_break_on_p9999() {
+        let worse = run(
+            "2026-04-21T10:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 10.0, 30.0],
+            500.0,
+        );
+        let better = run(
+            "2026-04-21T10:10:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 10.0, 20.0],
+            90.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&worse, 
&better]).expect("pick");
+        assert_eq!(picked.timestamp, better.timestamp);
+    }
+
+    #[test]
+    fn given_tie_on_all_latencies_when_picking_should_break_on_throughput() {
+        let low_tput = run(
+            "2026-04-21T10:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 10.0, 20.0],
+            100.0,
+        );
+        let high_tput = run(
+            "2026-04-21T10:10:00Z",
+            "hw-a",
+            "0.7.0",
+            [2.0, 10.0, 20.0],
+            200.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&low_tput, 
&high_tput]).expect("pick");
         assert_eq!(picked.timestamp, high_tput.timestamp);
     }
 
     #[test]
-    fn given_runs_outside_window_when_picking_should_ignore_old_runs() {
-        let old = benchmark("2026-04-20T10:00:00Z", 1.0, 500.0);
-        let fresh_slow = benchmark("2026-04-21T12:00:00Z", 10.0, 100.0);
-        let fresh_fast = benchmark("2026-04-21T12:30:00Z", 5.0, 90.0);
-        let picked = pick_best_from_recent_batch(&[&old, &fresh_slow, 
&fresh_fast])
-            .expect("expected a pick");
-        assert_eq!(picked.timestamp, fresh_fast.timestamp);
+    fn 
given_runs_from_older_release_when_picking_should_restrict_to_latest_sweep() {
+        let old_release = run(
+            "2025-01-15T10:00:00Z",
+            "hw-a",
+            "0.5.0",
+            [1.0, 5.0, 10.0],
+            500.0,
+        );
+        let current_slow = run(
+            "2026-04-21T12:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [10.0, 15.0, 25.0],
+            100.0,
+        );
+        let current_fast = run(
+            "2026-04-21T12:30:00Z",
+            "hw-a",
+            "0.7.0",
+            [5.0, 12.0, 22.0],
+            90.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&old_release, 
&current_slow, &current_fast])
+            .expect("pick");
+        assert_eq!(picked.timestamp, current_fast.timestamp);
+    }
+
+    #[test]
+    fn 
given_runs_on_different_hardware_when_picking_should_restrict_to_latest_sweep() 
{
+        let other_hw = run(
+            "2026-04-21T12:40:00Z",
+            "hw-b",
+            "0.7.0",
+            [1.0, 5.0, 10.0],
+            500.0,
+        );
+        let current = run(
+            "2026-04-21T12:30:00Z",
+            "hw-a",
+            "0.7.0",
+            [5.0, 12.0, 22.0],
+            90.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&other_hw, 
&current]).expect("pick");
+        assert_eq!(picked.timestamp, other_hw.timestamp);
+    }
+
+    #[test]
+    fn 
given_latest_sweep_helper_when_called_should_filter_to_newest_hardware_gitref_group()
 {
+        let old = run(
+            "2026-04-20T10:00:00Z",
+            "hw-a",
+            "0.6.0",
+            [1.0, 5.0, 10.0],
+            100.0,
+        );
+        let latest_a = run(
+            "2026-04-21T12:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [5.0, 10.0, 20.0],
+            100.0,
+        );
+        let latest_b = run(
+            "2026-04-21T12:30:00Z",
+            "hw-a",
+            "0.7.0",
+            [3.0, 8.0, 18.0],
+            120.0,
+        );
+        let sweep = latest_sweep(&[&old, &latest_a, &latest_b]);
+        assert_eq!(sweep.len(), 2);
+        assert!(
+            sweep
+                .iter()
+                .any(|report| report.timestamp == latest_a.timestamp)
+        );
+        assert!(
+            sweep
+                .iter()
+                .any(|report| report.timestamp == latest_b.timestamp)
+        );
     }
 
     #[test]
     fn given_nan_p99_when_picking_should_prefer_finite_values() {
-        let mut nan_run = benchmark("2026-04-21T10:00:00Z", 0.0, 100.0);
+        let mut nan_run = run(
+            "2026-04-21T10:00:00Z",
+            "hw-a",
+            "0.7.0",
+            [0.0, 0.0, 0.0],
+            100.0,
+        );
         nan_run.group_metrics[0].summary.average_p99_latency_ms = f64::NAN;
-        let good = benchmark("2026-04-21T10:10:00Z", 3.0, 80.0);
-        let picked = pick_best_from_recent_batch(&[&nan_run, 
&good]).expect("expected a pick");
+        let good = run(
+            "2026-04-21T10:10:00Z",
+            "hw-a",
+            "0.7.0",
+            [3.0, 6.0, 12.0],
+            80.0,
+        );
+        let picked = pick_best_from_recent_batch(&[&nan_run, 
&good]).expect("pick");
         assert_eq!(picked.timestamp, good.timestamp);
     }
 
-    fn benchmark(timestamp: &str, p99_ms: f64, throughput_mb_s: f64) -> 
BenchmarkReportLight {
+    #[test]
+    fn given_shared_recent_feed_when_picking_should_match_sidebar_top_sweep() {
+        let recent_feed_from_api = [
+            run(
+                "2026-04-21T13:30:00Z",
+                "hw-a",
+                "0.7.0",
+                [5.0, 12.0, 22.0],
+                140.0,
+            ),
+            run(
+                "2026-04-21T13:20:00Z",
+                "hw-a",
+                "0.7.0",
+                [2.0, 9.0, 19.0],
+                90.0,
+            ),
+            run(
+                "2026-04-21T13:10:00Z",
+                "hw-a",
+                "0.7.0",
+                [3.0, 10.0, 21.0],
+                120.0,
+            ),
+            run(
+                "2024-02-01T10:00:00Z",
+                "hw-legacy",
+                "0.3.0",
+                [1.0, 4.0, 8.0],
+                999.0,
+            ),
+        ];
+        let refs: Vec<&BenchmarkReportLight> = 
recent_feed_from_api.iter().collect();
+
+        let sidebar_top_sweep_key = (
+            recent_feed_from_api[0].hardware.identifier.clone(),
+            recent_feed_from_api[0].params.gitref.clone(),
+        );
+        let sweep = latest_sweep(&refs);
+        for report in &sweep {
+            assert_eq!(
+                (
+                    report.hardware.identifier.clone(),
+                    report.params.gitref.clone()
+                ),
+                sidebar_top_sweep_key,
+                "hero sweep leaked outside sidebar's newest (hardware, gitref)"
+            );
+        }
+
+        let picked = pick_best_from_recent_batch(&refs).expect("pick");
+        assert_eq!(picked.hardware.identifier, sidebar_top_sweep_key.0);
+        assert_eq!(picked.params.gitref, sidebar_top_sweep_key.1);
+        assert_eq!(picked.timestamp, recent_feed_from_api[1].timestamp);
+    }
+
+    fn run(
+        timestamp: &str,
+        hardware: &str,
+        gitref: &str,
+        latencies: [f64; 3],
+        throughput_mb_s: f64,
+    ) -> BenchmarkReportLight {
+        let [p99, p999, p9999] = latencies;
         let mut report = BenchmarkReportLight {
             timestamp: timestamp.to_string(),
             ..Default::default()
         };
+        report.hardware.identifier = Some(hardware.to_string());
+        report.params.gitref = Some(gitref.to_string());
         report.group_metrics.push(BenchmarkGroupMetricsLight {
-            summary: summary_with(throughput_mb_s, p99_ms),
+            summary: summary_with(throughput_mb_s, p99, p999, p9999),
             latency_distribution: None,
         });
         report
     }
 
-    fn summary_with(throughput_mb_s: f64, p99_ms: f64) -> 
BenchmarkGroupMetricsSummary {
+    fn summary_with(
+        throughput_mb_s: f64,
+        p99: f64,
+        p999: f64,
+        p9999: f64,
+    ) -> BenchmarkGroupMetricsSummary {
         BenchmarkGroupMetricsSummary {
             kind: GroupMetricsKind::Producers,
             total_throughput_megabytes_per_second: throughput_mb_s,
@@ -413,9 +717,9 @@ mod tests {
             average_p50_latency_ms: 0.0,
             average_p90_latency_ms: 0.0,
             average_p95_latency_ms: 0.0,
-            average_p99_latency_ms: p99_ms,
-            average_p999_latency_ms: 0.0,
-            average_p9999_latency_ms: 0.0,
+            average_p99_latency_ms: p99,
+            average_p999_latency_ms: p999,
+            average_p9999_latency_ms: p9999,
             average_latency_ms: 0.0,
             average_median_latency_ms: 0.0,
             min_latency_ms: 0.0,
diff --git a/core/bench/dashboard/frontend/src/state/ui.rs 
b/core/bench/dashboard/frontend/src/state/ui.rs
index 7b4dd68de..c3b241380 100644
--- a/core/bench/dashboard/frontend/src/state/ui.rs
+++ b/core/bench/dashboard/frontend/src/state/ui.rs
@@ -22,14 +22,6 @@ use std::collections::HashSet;
 use std::rc::Rc;
 use yew::prelude::*;
 
-#[derive(Clone, Debug, PartialEq)]
-#[allow(dead_code)]
-pub enum ViewMode {
-    SingleGitref,
-    GitrefTrend,
-    RecentBenchmarks,
-}
-
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct ParamRange {
     pub from: Option<u32>,
@@ -201,7 +193,6 @@ impl KindGroup {
 
 #[derive(Clone, Debug, PartialEq)]
 pub struct UiState {
-    pub view_mode: ViewMode,
     pub selected_measurement: MeasurementType,
     pub is_benchmark_tooltip_visible: bool,
     pub is_server_stats_tooltip_visible: bool,
@@ -212,12 +203,13 @@ pub struct UiState {
     pub sidebar_search: String,
     pub sidebar_sort: SidebarSort,
     pub sidebar_kind_filter: HashSet<KindGroup>,
+    pub hardware_filter: Option<String>,
+    pub gitref_filter: Option<String>,
 }
 
 impl Default for UiState {
     fn default() -> Self {
         Self {
-            view_mode: ViewMode::SingleGitref,
             selected_measurement: MeasurementType::Latency,
             is_benchmark_tooltip_visible: false,
             is_server_stats_tooltip_visible: false,
@@ -228,6 +220,8 @@ impl Default for UiState {
             sidebar_search: String::new(),
             sidebar_sort: SidebarSort::default(),
             sidebar_kind_filter: HashSet::new(),
+            hardware_filter: None,
+            gitref_filter: None,
         }
     }
 }
@@ -242,7 +236,6 @@ pub enum TopBarPopup {
 pub enum UiAction {
     SetMeasurementType(MeasurementType),
     TogglePopup(TopBarPopup),
-    SetViewMode(ViewMode),
     SetParamRange(ParamField, ParamRange),
     SetMetricRange(MetricField, MetricRange),
     ClearParamFilters,
@@ -252,6 +245,8 @@ pub enum UiAction {
     SetSidebarSearch(String),
     SetSidebarSort(SidebarSort),
     ToggleKindFilter(KindGroup),
+    SetHardwareFilter(Option<String>),
+    SetGitrefFilter(Option<String>),
 }
 
 impl Reducible for UiState {
@@ -285,8 +280,12 @@ impl Reducible for UiState {
                     ..(*self).clone()
                 }
             }
-            UiAction::SetViewMode(vm) => UiState {
-                view_mode: vm,
+            UiAction::SetHardwareFilter(value) => UiState {
+                hardware_filter: value,
+                ..(*self).clone()
+            },
+            UiAction::SetGitrefFilter(value) => UiState {
+                gitref_filter: value,
                 ..(*self).clone()
             },
             UiAction::SetParamRange(field, range) => {
diff --git a/core/bench/dashboard/frontend/src/version.rs 
b/core/bench/dashboard/frontend/src/version.rs
new file mode 100644
index 000000000..9e452b45b
--- /dev/null
+++ b/core/bench/dashboard/frontend/src/version.rs
@@ -0,0 +1,180 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::cmp::Ordering;
+
+/// Recency key derived from a semver-like gitref such as `0.7.0` or
+/// `0.7.0-edge.1`. Larger = more recent.
+///
+/// Ordering rules (differ from strict semver because suffixes in this
+/// project denote post-release nightlies, not pre-release candidates):
+/// - Compare `(major, minor, patch)` first.
+/// - On equal base, a suffixed build (`-edge.N`, `-dev.N`, ...) ranks
+///   ABOVE the plain release, because nightlies ship AFTER the tag.
+/// - Two suffixed builds compare by suffix build number, then tag name.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct SemverRecency {
+    pub major: u32,
+    pub minor: u32,
+    pub patch: u32,
+    pub suffix: Option<SemverSuffix>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct SemverSuffix {
+    pub tag: String,
+    pub number: u32,
+}
+
+impl Ord for SemverRecency {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.major
+            .cmp(&other.major)
+            .then(self.minor.cmp(&other.minor))
+            .then(self.patch.cmp(&other.patch))
+            .then(cmp_suffix(self.suffix.as_ref(), other.suffix.as_ref()))
+    }
+}
+
+impl PartialOrd for SemverRecency {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+/// Parse a gitref into a recency key. Returns `None` for plain commit
+/// hashes or anything that doesn't match `X.Y.Z` / `X.Y.Z-tag[.N]`.
+pub fn parse_semver_recency(gitref: &str) -> Option<SemverRecency> {
+    let raw = gitref.trim().trim_start_matches('v');
+    let (base, suffix_str) = match raw.split_once('-') {
+        Some((base, rest)) => (base, Some(rest)),
+        None => (raw, None),
+    };
+    let mut parts = base.split('.');
+    let major = parts.next()?.parse::<u32>().ok()?;
+    let minor = parts.next()?.parse::<u32>().ok()?;
+    let patch = parts.next()?.parse::<u32>().ok()?;
+    if parts.next().is_some() {
+        return None;
+    }
+    let suffix = suffix_str.map(parse_suffix);
+    Some(SemverRecency {
+        major,
+        minor,
+        patch,
+        suffix,
+    })
+}
+
+fn parse_suffix(raw: &str) -> SemverSuffix {
+    match raw.rsplit_once('.') {
+        Some((tag, number)) if !tag.is_empty() => SemverSuffix {
+            tag: tag.to_string(),
+            number: number.parse().unwrap_or(0),
+        },
+        _ => SemverSuffix {
+            tag: raw.to_string(),
+            number: 0,
+        },
+    }
+}
+
+fn cmp_suffix(left: Option<&SemverSuffix>, right: Option<&SemverSuffix>) -> 
Ordering {
+    match (left, right) {
+        (None, None) => Ordering::Equal,
+        (Some(_), None) => Ordering::Greater,
+        (None, Some(_)) => Ordering::Less,
+        (Some(l), Some(r)) => l.number.cmp(&r.number).then_with(|| 
l.tag.cmp(&r.tag)),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn given_plain_commit_hash_when_parsing_should_return_none() {
+        assert!(parse_semver_recency("abc123").is_none());
+        assert!(parse_semver_recency("main").is_none());
+        assert!(parse_semver_recency("0.7").is_none());
+        assert!(parse_semver_recency("0.7.0.1").is_none());
+    }
+
+    #[test]
+    fn given_plain_semver_when_parsing_should_yield_base_only() {
+        let key = parse_semver_recency("0.7.0").expect("parse");
+        assert_eq!(key.major, 0);
+        assert_eq!(key.minor, 7);
+        assert_eq!(key.patch, 0);
+        assert!(key.suffix.is_none());
+    }
+
+    #[test]
+    fn given_suffixed_version_when_parsing_should_capture_tag_and_number() {
+        let key = parse_semver_recency("0.7.0-edge.1").expect("parse");
+        let suffix = key.suffix.as_ref().expect("suffix");
+        assert_eq!(suffix.tag, "edge");
+        assert_eq!(suffix.number, 1);
+    }
+
+    #[test]
+    fn given_leading_v_when_parsing_should_still_match() {
+        let key = parse_semver_recency("v0.7.0-dev.4").expect("parse");
+        assert_eq!(key.major, 0);
+        assert_eq!(key.suffix.as_ref().expect("suffix").tag.as_str(), "dev");
+    }
+
+    #[test]
+    fn 
given_suffixed_and_plain_same_base_when_comparing_should_rank_suffixed_higher() 
{
+        let edge = parse_semver_recency("0.7.0-edge.1").expect("parse");
+        let plain = parse_semver_recency("0.7.0").expect("parse");
+        assert!(edge > plain);
+    }
+
+    #[test]
+    fn given_bigger_base_when_comparing_should_win_regardless_of_suffix() {
+        let plain_newer = parse_semver_recency("0.7.0").expect("parse");
+        let edge_older = parse_semver_recency("0.6.9-dev.4").expect("parse");
+        assert!(plain_newer > edge_older);
+    }
+
+    #[test]
+    fn 
given_same_suffix_tag_different_numbers_when_comparing_should_prefer_higher_number()
 {
+        let first = parse_semver_recency("0.7.0-edge.1").expect("parse");
+        let fifth = parse_semver_recency("0.7.0-edge.5").expect("parse");
+        assert!(fifth > first);
+    }
+
+    #[test]
+    fn given_user_example_sequence_when_sorting_should_order_newest_first() {
+        let mut entries = [
+            parse_semver_recency("0.6.9-dev.4").expect("parse"),
+            parse_semver_recency("0.7.0-edge.1").expect("parse"),
+            parse_semver_recency("0.7.0").expect("parse"),
+        ];
+        entries.sort_by(|left, right| right.cmp(left));
+        assert_eq!(
+            entries[0],
+            parse_semver_recency("0.7.0-edge.1").expect("parse")
+        );
+        assert_eq!(entries[1], parse_semver_recency("0.7.0").expect("parse"));
+        assert_eq!(
+            entries[2],
+            parse_semver_recency("0.6.9-dev.4").expect("parse")
+        );
+    }
+}
diff --git a/core/bench/report/src/plotting/chart.rs 
b/core/bench/report/src/plotting/chart.rs
index 5a2e02d67..b56b1bd04 100644
--- a/core/bench/report/src/plotting/chart.rs
+++ b/core/bench/report/src/plotting/chart.rs
@@ -77,13 +77,7 @@ impl IggyChart {
                     .item_height(14)
                     .type_(LegendType::Scroll),
             )
-            .grid(
-                Grid::new()
-                    .left("5%")
-                    .right("20%")
-                    .top(grid_top)
-                    .bottom("8%"),
-            )
+            .grid(Grid::new().left(70).right("20%").top(grid_top).bottom("8%"))
             .data_zoom(
                 DataZoom::new()
                     .show(true)
@@ -145,9 +139,10 @@ impl IggyChart {
             Axis::new()
                 .type_(AxisType::Value)
                 .name(axis_label)
-                .name_location(NameLocation::End)
+                .name_location(NameLocation::Middle)
+                .name_rotation(90)
                 .name_text_style(TextStyle::new().font_size(AXIS_TEXT_SIZE))
-                .name_gap(15)
+                .name_gap(44)
                 .position("left")
                 .axis_label(AxisLabel::new())
                 .split_line(SplitLine::new().show(true)),
@@ -162,8 +157,9 @@ impl IggyChart {
             Axis::new()
                 .type_(AxisType::Value)
                 .name(y1_label)
-                .name_location(NameLocation::End)
-                .name_gap(15)
+                .name_location(NameLocation::Middle)
+                .name_rotation(90)
+                .name_gap(44)
                 .name_text_style(TextStyle::new().font_size(AXIS_TEXT_SIZE))
                 .position("left")
                 .axis_label(AxisLabel::new())
@@ -174,9 +170,10 @@ impl IggyChart {
             Axis::new()
                 .type_(AxisType::Value)
                 .name(y2_label)
-                .name_location(NameLocation::End)
+                .name_location(NameLocation::Middle)
+                .name_rotation(-90)
                 .name_text_style(TextStyle::new().font_size(AXIS_TEXT_SIZE))
-                .name_gap(15)
+                .name_gap(54)
                 .position("right")
                 .axis_label(AxisLabel::new())
                 .split_line(SplitLine::new().show(true)),

Reply via email to