From 8052cefd464cd2634613473a95cbeed5a2df2786 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Wed, 24 Jun 2026 20:21:15 +0800 Subject: [PATCH] feat(ui): add keyboard shortcut cue in search bar, fix clear button positioning --- static/css/components/header.css | 77 ++++++++++++++++++- static/js/managers/SearchManager.js | 10 ++- templates/components/header.html | 1 + .../components/pageControls.filtering.test.js | 35 +++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/static/css/components/header.css b/static/css/components/header.css index 3ae3ae8a..e4e5a8f4 100644 --- a/static/css/components/header.css +++ b/static/css/components/header.css @@ -149,7 +149,7 @@ width: 100%; padding: 0.5rem 0.75rem; padding-left: 2.25rem !important; - padding-right: 5rem !important; + padding-right: 6.75rem !important; /* clear room for options + filter + clear/cue toggles */ border: none; background: transparent; color: var(--text-color); @@ -190,6 +190,81 @@ right: 2.25rem; } +/* Clear button: sit immediately left of the search-options toggle */ +.header-search .search-clear { + position: absolute; + right: 4.25rem; /* 2.25rem (options toggle) + 28px toggle width + 4px gap */ + top: 50%; + transform: translateY(-50%); + width: 28px; + height: 28px; + display: none; + align-items: center; + justify-content: center; + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + border-radius: var(--border-radius-xs, 4px); + padding: 0; + line-height: 1; + transition: background-color var(--transition-base), color var(--transition-base); +} + +.header-search .search-clear.visible { + display: flex; +} + +.header-search .search-clear:hover { + background: color-mix(in oklch, var(--text-muted) 15%, transparent); + color: var(--lora-accent); +} + +/* Keyboard shortcut cue: shown when search is empty, hidden when typing */ +.header-search .search-shortcut-cue { + position: absolute; + right: 4.25rem; /* same slot as clear button */ + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + gap: 2px; + pointer-events: none; + font-family: inherit; + font-size: 0.7rem; + line-height: 1; + color: var(--text-muted); + opacity: 0.7; + white-space: nowrap; + transition: opacity 0.2s ease; +} + +.header-search .search-shortcut-cue kbd { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + padding: 0 4px; + font-family: inherit; + font-size: 0.68rem; + font-weight: 500; + color: var(--text-muted); + /* Subtle tint derived from text color so it adapts to both light & dark themes */ + background: color-mix(in oklch, var(--text-muted) 12%, transparent); + border: 1px solid color-mix(in oklch, var(--text-muted) 25%, transparent); + border-radius: var(--border-radius-xs, 3px); + line-height: 1; +} + +.header-search .search-shortcut-cue.hidden { + display: none; +} + +.header-search.disabled .search-shortcut-cue { + display: none; +} + .header-search .search-options-toggle:hover, .header-search .search-filter-toggle:hover, .header-search .search-filter-toggle:focus-visible { diff --git a/static/js/managers/SearchManager.js b/static/js/managers/SearchManager.js index b82e1232..21fd7b08 100644 --- a/static/js/managers/SearchManager.js +++ b/static/js/managers/SearchManager.js @@ -27,6 +27,9 @@ export class SearchManager { // Create clear button for search input this.createClearButton(); + // Keyboard shortcut cue element (static, exists in the HTML) + this.searchShortcutCue = document.getElementById('searchShortcutCue'); + this.initEventListeners(); this.loadSearchPreferences(); this.setupKeyboardShortcuts(); @@ -163,8 +166,13 @@ export class SearchManager { } updateClearButtonVisibility() { + const hasText = this.searchInput.value.length > 0; if (this.clearButton) { - this.clearButton.classList.toggle('visible', this.searchInput.value.length > 0); + this.clearButton.classList.toggle('visible', hasText); + } + // Toggle the keyboard shortcut cue: visible only when search is empty + if (this.searchShortcutCue) { + this.searchShortcutCue.classList.toggle('hidden', hasText); } } diff --git a/templates/components/header.html b/templates/components/header.html index fa106056..a039bb41 100644 --- a/templates/components/header.html +++ b/templates/components/header.html @@ -53,6 +53,7 @@ + CtrlF