-
${escapeHtml(result.cluster)} → ${escapeHtml(result.tab)}
-
${result.matches} match${result.matches > 1 ? 'es' : ''}
+
+
-
${result.snippet}
-
+
${escapeHtml(result.cluster)}
+
${result.snippet}
+
`;
});
@@ -218,10 +245,9 @@
resultsDiv.innerHTML = html;
// Add click handlers to results
- const resultLinks = resultsDiv.querySelectorAll('.cluster-search-result');
- resultLinks.forEach(function(link) {
- link.addEventListener('click', function(e) {
- e.preventDefault();
+ const resultItems = resultsDiv.querySelectorAll('.search-result-item');
+ resultItems.forEach(function(item) {
+ item.addEventListener('click', function() {
const tabId = this.getAttribute('data-tab-id');
const result = results.find(r => r.tabId === tabId);
if (result) {
@@ -229,12 +255,16 @@
highlightMatches(result.tabPane, query);
// Scroll to the section
result.section.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ // Mark as active
+ resultItems.forEach(r => r.classList.remove('active'));
+ this.classList.add('active');
}
});
});
// Auto-expand first result
if (results.length > 0) {
+ resultItems[0].classList.add('active');
activateTab(results[0]);
highlightMatches(results[0].tabPane, query);
}
@@ -322,31 +352,195 @@
});
}
- // Add CSS for highlighting
+ // Add CSS for sidebar and highlighting
const style = document.createElement('style');
style.textContent = `
+ /* Highlight styling */
.cluster-highlight {
background-color: #ffeb3b;
padding: 2px 0;
font-weight: bold;
}
- .cluster-search-container {
- position: sticky;
- top: 70px;
+ /* Sidebar toggle button */
+ .cluster-search-toggle {
+ position: fixed;
+ left: 0;
+ top: 200px;
+ background: #007bff;
+ color: white;
+ border: none;
+ border-radius: 0 5px 5px 0;
+ padding: 12px 15px;
+ cursor: pointer;
+ z-index: 1000;
+ box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
+ font-size: 14px;
+ transition: background 0.3s;
+ }
+
+ .cluster-search-toggle:hover {
+ background: #0056b3;
+ }
+
+ .cluster-search-toggle i {
+ margin-right: 5px;
+ }
+
+ /* Sidebar panel */
+ .cluster-search-panel {
+ position: fixed;
+ left: -350px;
+ top: 0;
+ width: 350px;
+ height: 100vh;
background: white;
- z-index: 100;
- padding: 20px 0 10px 0;
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ box-shadow: 2px 0 10px rgba(0,0,0,0.1);
+ z-index: 1001;
+ transition: left 0.3s ease;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ }
+
+ .cluster-search-panel.open {
+ left: 0;
+ }
+
+ /* Sidebar header */
+ .cluster-search-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ border-bottom: 1px solid #dee2e6;
+ background: #f8f9fa;
+ }
+
+ .cluster-search-header h4 {
+ margin: 0;
+ font-size: 18px;
+ color: #333;
}
- .cluster-search-result:hover {
+ .cluster-search-close {
+ background: none;
+ border: none;
+ font-size: 20px;
+ color: #666;
cursor: pointer;
+ padding: 5px;
+ line-height: 1;
+ }
+
+ .cluster-search-close:hover {
+ color: #333;
+ }
+
+ /* Sidebar body */
+ .cluster-search-body {
+ padding: 20px;
+ flex: 1;
+ overflow-y: auto;
+ }
+
+ /* Search results summary */
+ .search-summary {
+ background: #e7f3ff;
+ padding: 10px;
+ border-radius: 5px;
+ margin-bottom: 15px;
+ font-size: 0.9rem;
+ color: #004085;
}
- .cluster-search-result mark {
+ /* Search results list */
+ .search-results-list {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ /* Individual search result */
+ .search-result-item {
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 5px;
+ padding: 12px;
+ cursor: pointer;
+ transition: all 0.2s;
+ }
+
+ .search-result-item:hover {
+ background: #e9ecef;
+ border-color: #007bff;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
+ }
+
+ .search-result-item.active {
+ background: #e7f3ff;
+ border-color: #007bff;
+ box-shadow: inset 0 0 0 1px #007bff;
+ }
+
+ .search-result-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 5px;
+ }
+
+ .search-result-header strong {
+ font-size: 0.95rem;
+ color: #333;
+ flex: 1;
+ margin-right: 10px;
+ }
+
+ .search-result-header .badge {
+ font-size: 0.75rem;
+ }
+
+ .search-result-cluster {
+ font-size: 0.8rem;
+ color: #666;
+ margin-bottom: 8px;
+ }
+
+ .search-result-snippet {
+ font-size: 0.8rem;
+ color: #555;
+ line-height: 1.4;
+ }
+
+ .search-result-snippet mark {
background-color: #ffeb3b;
padding: 1px 2px;
+ font-weight: 600;
+ }
+
+ /* Mobile responsive */
+ @media (max-width: 768px) {
+ .cluster-search-panel {
+ width: 100%;
+ left: -100%;
+ }
+
+ .cluster-search-panel.open {
+ left: 0;
+ }
+
+ .cluster-search-toggle {
+ top: 150px;
+ font-size: 12px;
+ padding: 10px 12px;
+ }
+ }
+
+ /* Alert styling in sidebar */
+ .cluster-search-body .alert {
+ font-size: 0.85rem;
+ padding: 8px 12px;
}
`;
document.head.appendChild(style);
From 1d0a2a9a45e8e676512a8321f1f371c0476fcd74 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 17:10:30 +0000
Subject: [PATCH 5/6] [WIP] Fix search function layout on cluster page (#654)
* Initial plan
* Fix search panel visibility and scroll behavior
Co-authored-by: LukasWallrich <60155545+LukasWallrich@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LukasWallrich <60155545+LukasWallrich@users.noreply.github.com>
Co-authored-by: Lukas Wallrich
---
static/js/clusters-search.js | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/static/js/clusters-search.js b/static/js/clusters-search.js
index 9dcf05146f..fb14e51c55 100644
--- a/static/js/clusters-search.js
+++ b/static/js/clusters-search.js
@@ -253,8 +253,8 @@
if (result) {
activateTab(result);
highlightMatches(result.tabPane, query);
- // Scroll to the section
- result.section.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ // Scroll to the section with offset for navbar
+ scrollToElement(result.section);
// Mark as active
resultItems.forEach(r => r.classList.remove('active'));
this.classList.add('active');
@@ -295,6 +295,22 @@
});
}
+ function scrollToElement(element) {
+ // Get navbar height to offset the scroll
+ const navbar = document.querySelector('.navbar-fixed-top, .fixed-top, nav.navbar');
+ const navbarHeight = navbar ? navbar.offsetHeight : 70;
+
+ // Calculate the position to scroll to
+ const elementPosition = element.getBoundingClientRect().top + window.pageYOffset;
+ const offsetPosition = elementPosition - navbarHeight - 20; // Extra 20px padding
+
+ // Scroll to the calculated position
+ window.scrollTo({
+ top: offsetPosition,
+ behavior: 'smooth'
+ });
+ }
+
function highlightMatches(tabPane, query) {
if (!tabPane) return;
@@ -373,7 +389,7 @@
border-radius: 0 5px 5px 0;
padding: 12px 15px;
cursor: pointer;
- z-index: 1000;
+ z-index: 1034;
box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
font-size: 14px;
transition: background 0.3s;
@@ -396,7 +412,7 @@
height: 100vh;
background: white;
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
- z-index: 1001;
+ z-index: 1035;
transition: left 0.3s ease;
display: flex;
flex-direction: column;
From f45d03928085b3d718ea5f8a8db83b3c59931064 Mon Sep 17 00:00:00 2001
From: richarddushime
Date: Wed, 18 Feb 2026 21:44:43 +0100
Subject: [PATCH 6/6] fix: improve clusters search panel UX
- Auto-hide panel when clicking search result
- Position panel below navbar to avoid hiding logo
- Reduce panel width to 70% on mobile devices
- Show only search icon on mobile toggle button
---
static/js/clusters-search.js | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/static/js/clusters-search.js b/static/js/clusters-search.js
index fb14e51c55..02e64aad78 100644
--- a/static/js/clusters-search.js
+++ b/static/js/clusters-search.js
@@ -29,7 +29,7 @@
sidebar.className = 'cluster-search-sidebar';
sidebar.innerHTML = `
- Search Clusters
+ Search Clusters