From 71b347b4bb5ddc5688b84a9049c38c8b7e698369 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Wed, 25 Feb 2026 13:26:59 +0800 Subject: [PATCH] fix(settings): Auto-scroll to first search match in settings modal When searching in settings, the view now automatically scrolls to the first matching element after switching to the matching section. - Modified performSearch() to track and scroll to first match - Modified highlightSearchMatches() to return the first highlight element - Uses requestAnimationFrame and scrollIntoView with block: 'center' --- static/js/managers/SettingsManager.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index cf1a939a..195e5aa1 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -476,6 +476,7 @@ export class SettingsManager { const lowerQuery = query.toLowerCase(); let firstMatchSection = null; + let firstMatchElement = null; let matchCount = 0; sections.forEach(section => { @@ -483,12 +484,13 @@ export class SettingsManager { const hasMatch = sectionText.includes(lowerQuery); if (hasMatch) { - this.highlightSearchMatches(section, lowerQuery); + const firstHighlight = this.highlightSearchMatches(section, lowerQuery); matchCount++; // Track first match to auto-switch if (!firstMatchSection) { firstMatchSection = section; + firstMatchElement = firstHighlight; } } else { this.removeSearchHighlights(section); @@ -512,6 +514,16 @@ export class SettingsManager { item.classList.add('active'); } }); + + // Scroll to first match after a short delay to allow section to become visible + if (firstMatchElement) { + requestAnimationFrame(() => { + firstMatchElement.scrollIntoView({ + behavior: 'smooth', + block: 'center' + }); + }); + } } // Show empty state if no matches found @@ -545,10 +557,11 @@ export class SettingsManager { // Remove existing highlights first this.removeSearchHighlights(section); - if (!query) return; + if (!query) return null; // Highlight in labels and help text const textElements = section.querySelectorAll('label, .input-help, h3'); + let firstHighlight = null; textElements.forEach(element => { const walker = document.createTreeWalker( @@ -588,6 +601,11 @@ export class SettingsManager { highlight.textContent = text.substring(index, index + query.length); parts.push(highlight); + // Track first highlight for scrolling + if (!firstHighlight) { + firstHighlight = highlight; + } + lastIndex = index + query.length; } @@ -603,6 +621,8 @@ export class SettingsManager { } }); }); + + return firstHighlight; } removeSearchHighlights(section) {