From c674cb58924a8a91f9cef52489e073c77bc9cfa3 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 16:48:13 +0100 Subject: [PATCH 1/5] Add "discard" (cross) button in search bars --- index.html | 11 +++++++++++ js/app.js | 3 +++ js/ui.js | 30 ++++++++++++++++++++++++++++++ styles.css | 16 ++++++++++++++-- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 233b51d..7ec8866 100644 --- a/index.html +++ b/index.html @@ -1073,6 +1073,14 @@ autocapitalize="off" spellcheck="false" /> + @@ -1649,6 +1657,9 @@ placeholder="Search tracks..." class="track-list-search-input" /> +
diff --git a/js/app.js b/js/app.js index 43cb84c..78f9661 100644 --- a/js/app.js +++ b/js/app.js @@ -1274,6 +1274,9 @@ document.addEventListener('DOMContentLoaded', async () => { const searchForm = document.getElementById('search-form'); const searchInput = document.getElementById('search-input'); + // Setup clear button for search bar + ui.setupSearchClearButton(searchInput); + const performSearch = debounce((query) => { if (query) { navigate(`/search/${encodeURIComponent(query)}`); diff --git a/js/ui.js b/js/ui.js index ad3d21a..e674067 100644 --- a/js/ui.js +++ b/js/ui.js @@ -539,6 +539,33 @@ export class UIRenderer { .join('')}`; } + setupSearchClearButton(inputElement, clearBtnSelector = '.search-clear-btn') { + if (!inputElement) return; + + const clearBtn = inputElement.parentElement?.querySelector(clearBtnSelector); + if (!clearBtn) return; + + // Remove old listener if exists + const oldListener = clearBtn._clearListener; + if (oldListener) clearBtn.removeEventListener('click', oldListener); + + // Toggle visibility based on input value + const toggleVisibility = () => { + clearBtn.style.display = inputElement.value.trim() ? 'flex' : 'none'; + }; + + // Clear input on click + const clearListener = () => { + inputElement.value = ''; + inputElement.dispatchEvent(new Event('input')); + inputElement.focus(); + }; + + inputElement.addEventListener('input', toggleVisibility); + clearBtn._clearListener = clearListener; + clearBtn.addEventListener('click', clearListener); + } + setupTracklistSearch( searchInputId = 'track-list-search-input', tracklistContainerId = 'playlist-detail-tracklist' @@ -548,6 +575,9 @@ export class UIRenderer { if (!searchInput || !tracklistContainer) return; + // Setup clear button + this.setupSearchClearButton(searchInput); + // Remove previous listener if exists const oldListener = searchInput._searchListener; if (oldListener) { diff --git a/styles.css b/styles.css index 1501260..a8b764f 100644 --- a/styles.css +++ b/styles.css @@ -585,7 +585,7 @@ kbd { .search-bar input { width: 100%; - padding: 0.75rem 0.75rem 0.75rem 2.5rem; + padding: 0.75rem 2.5rem 0.75rem 2.5rem; background-color: var(--input); border: 1px solid var(--border); border-radius: var(--radius); @@ -597,6 +597,17 @@ kbd { background-color var(--transition-fast); } +/* Clear button for search inputs */ +.search-clear-btn { + position: absolute; + right: 0.25rem; + top: 50%; + transform: translateY(-50%); + font-size: 1.5rem; + line-height: 1; + z-index: 1; +} + .search-bar input:focus { outline: none; border-color: var(--ring); @@ -5519,11 +5530,12 @@ textarea:focus { /* Track List Search */ .track-list-search-container { margin: 1rem 0; + position: relative; } .track-list-search-input { width: 100%; - padding: 0.75rem 1rem; + padding: 0.75rem 2.5rem 0.75rem 1rem; background-color: var(--input); border: 1px solid var(--border); border-radius: var(--radius); From 81f654453ead83ca5f54602701240bbcb8c9b740 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 16:49:24 +0100 Subject: [PATCH 2/5] Discard search in playlist when leaving --- js/ui.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/ui.js b/js/ui.js index e674067..d05c99b 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1091,6 +1091,15 @@ export class UIRenderer { document.querySelector('.main-content').scrollTop = 0; + // Reset track list search when leaving playlist page + if (pageId !== 'playlist') { + const trackListSearchInput = document.getElementById('track-list-search-input'); + if (trackListSearchInput && trackListSearchInput.value) { + trackListSearchInput.value = ''; + trackListSearchInput.dispatchEvent(new Event('input')); + } + } + // Clear background and color if not on album, artist, playlist, or mix page if (!['album', 'artist', 'playlist', 'mix'].includes(pageId)) { this.setPageBackground(null); From 2482df31be606e46d41d8412e81f2839480ce569 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 16:53:35 +0100 Subject: [PATCH 3/5] move discard playlist search in a more optimal place --- js/ui.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/js/ui.js b/js/ui.js index d05c99b..73891c9 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1091,15 +1091,6 @@ export class UIRenderer { document.querySelector('.main-content').scrollTop = 0; - // Reset track list search when leaving playlist page - if (pageId !== 'playlist') { - const trackListSearchInput = document.getElementById('track-list-search-input'); - if (trackListSearchInput && trackListSearchInput.value) { - trackListSearchInput.value = ''; - trackListSearchInput.dispatchEvent(new Event('input')); - } - } - // Clear background and color if not on album, artist, playlist, or mix page if (!['album', 'artist', 'playlist', 'mix'].includes(pageId)) { this.setPageBackground(null); @@ -1983,6 +1974,11 @@ export class UIRenderer { async renderPlaylistPage(playlistId, source = null) { this.showPage('playlist'); + + // Reset search input for new playlist + const searchInput = document.getElementById('track-list-search-input'); + if (searchInput) searchInput.value = ''; + const imageEl = document.getElementById('playlist-detail-image'); const titleEl = document.getElementById('playlist-detail-title'); const metaEl = document.getElementById('playlist-detail-meta'); From c678a761d0be98b8c81d2372a2d930d2a5400fd5 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 17:05:36 +0100 Subject: [PATCH 4/5] fix playlist search bar want to register new credential in browser --- index.html | 27 +++++++++++++++++++++++---- styles.css | 13 ++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 7ec8866..cd9c907 100644 --- a/index.html +++ b/index.html @@ -1650,17 +1650,36 @@ -
+
+ + + + - -
+
Date: Thu, 5 Feb 2026 17:09:43 +0100 Subject: [PATCH 5/5] Clean & refactor css + linting --- index.html | 9 ++++-- styles.css | 91 +++++++++++++++++++++++------------------------------- 2 files changed, 45 insertions(+), 55 deletions(-) diff --git a/index.html b/index.html index cd9c907..724e297 100644 --- a/index.html +++ b/index.html @@ -1650,7 +1650,7 @@ -
+ -
diff --git a/styles.css b/styles.css index ab9a38a..49de3b9 100644 --- a/styles.css +++ b/styles.css @@ -474,14 +474,8 @@ kbd { } .search-bar svg.search-icon { - position: absolute; - left: 0.75rem; - top: 50%; - transform: translateY(-50%); - color: var(--muted-foreground); width: 20px; height: 20px; - pointer-events: none; } .sidebar-nav .nav-item a:hover { @@ -576,20 +570,11 @@ kbd { } .search-bar { - position: relative; width: 80%; max-width: 100%; - display: flex; - align-items: center; } .search-bar input { - width: 100%; - padding: 0.75rem 2.5rem 0.75rem 2.5rem; - background-color: var(--input); - border: 1px solid var(--border); - border-radius: var(--radius); - color: var(--foreground); font-size: 1rem; transition: box-shadow var(--transition-fast), @@ -597,7 +582,44 @@ kbd { background-color var(--transition-fast); } -/* Clear button for search inputs */ +/* Shared search bar styles */ +.search-bar, +.track-list-search-container { + position: relative; + display: flex; + align-items: center; +} + +.search-bar svg.search-icon, +.track-list-search-container svg.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + color: var(--muted-foreground); + pointer-events: none; +} + +.search-bar input, +.track-list-search-input { + width: 100%; + padding: 0.75rem 2.5rem; + background-color: var(--input); + border: 1px solid var(--border); + border-radius: var(--radius); + color: var(--foreground); + transition: + box-shadow var(--transition-fast), + border-color var(--transition-fast); +} + +.search-bar input:focus, +.track-list-search-input:focus { + outline: none; + border-color: var(--ring); + box-shadow: 0 0 0 3px rgb(var(--highlight-rgb) / 0.2); +} + .search-clear-btn { position: absolute; right: 0.25rem; @@ -608,12 +630,6 @@ kbd { z-index: 1; } -.search-bar input:focus { - outline: none; - border-color: var(--ring); - box-shadow: 0 0 0 3px rgb(var(--highlight-rgb), 0.2); -} - body.has-page-background .search-bar input { background-color: var(--background); } @@ -5530,39 +5546,8 @@ textarea:focus { /* Track List Search */ .track-list-search-container { margin: 1rem 0; - position: relative; - display: flex; - align-items: center; -} - -.track-list-search-container svg.search-icon { - position: absolute; - left: 0.75rem; - top: 50%; - transform: translateY(-50%); - color: var(--muted-foreground); - pointer-events: none; } .track-list-search-input { - width: 100%; - padding: 0.75rem 2.5rem 0.75rem 2.5rem; - background-color: var(--input); - border: 1px solid var(--border); - border-radius: var(--radius); - color: var(--foreground); font-size: 0.95rem; - transition: - box-shadow var(--transition-fast), - border-color var(--transition-fast); -} - -.track-list-search-input:focus { - outline: none; - border-color: var(--ring); - box-shadow: 0 0 0 3px rgb(var(--highlight-rgb) / 0.2); -} - -.track-list-search-input::placeholder { - color: var(--muted-foreground); }