diff --git a/index.html b/index.html index 233b51d..724e297 100644 --- a/index.html +++ b/index.html @@ -1073,6 +1073,14 @@ autocapitalize="off" spellcheck="false" /> + @@ -1642,14 +1650,41 @@ -
+
+ + + + -
+ +
{ 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..73891c9 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) { @@ -1944,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'); diff --git a/styles.css b/styles.css index 1501260..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 0.75rem 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,10 +582,52 @@ kbd { background-color var(--transition-fast); } -.search-bar input:focus { +/* 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); + box-shadow: 0 0 0 3px rgb(var(--highlight-rgb) / 0.2); +} + +.search-clear-btn { + position: absolute; + right: 0.25rem; + top: 50%; + transform: translateY(-50%); + font-size: 1.5rem; + line-height: 1; + z-index: 1; } body.has-page-background .search-bar input { @@ -5522,24 +5549,5 @@ textarea:focus { } .track-list-search-input { - width: 100%; - padding: 0.75rem 1rem; - 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); }