feat: persistent inline header search with overlay results
Replaces the hidden toggle-based mobile search bar with a permanently visible pill-shaped search input in the header row, next to the logo. - Search is always visible — no button click required - Typing shows a floating overlay with library results (artists, albums, songs) without navigating away from the current page - Clearing the input or navigating to any page closes the overlay silently - The ✕ clear button appears only while text is present - navigate() now calls closeHeaderSearch() so results disappear cleanly when tapping any result or bottom nav tab - Old toggleMobileSearch / closeMobileSearch kept as no-op stubs for safety Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
b7afa19f70
commit
36f968881b
5 files changed
+48
-38
No files matched your search
+2
-2
@@ -12,7 +12,7 @@ import {
|
||||
npToggleStar, updateMediaSession,
|
||||
} from './player.js';
|
||||
import {
|
||||
navigate, _navGoBack, _navLoad, onLocalSearch, onMobileSearch,
|
||||
navigate, _navGoBack, _navLoad, onHeaderSearch, closeHeaderSearch,
|
||||
onGlobalSearch, s_goArtist, s_goAlbum, playerBarGoArtist, playerBarGoAlbum,
|
||||
searchSimilarArtist, searchAndPreview, loadItunesAlbum, expandArtistBio,
|
||||
loadAlbums, loadStarred, loadRandom, filterStarred, filterPlaylist,
|
||||
@@ -293,7 +293,7 @@ try { history.replaceState({ nsIdx: 0 }, '', ''); } catch {}
|
||||
// ─── EXPOSE GLOBALS (for HTML onclick attributes) ───
|
||||
Object.assign(window, {
|
||||
// Navigation
|
||||
navigate, onLocalSearch, onMobileSearch, onGlobalSearch, s_goArtist, s_goAlbum,
|
||||
navigate, onHeaderSearch, closeHeaderSearch, onGlobalSearch, s_goArtist, s_goAlbum,
|
||||
playerBarGoArtist, playerBarGoAlbum, searchSimilarArtist, searchAndPreview,
|
||||
loadItunesAlbum, expandArtistBio,
|
||||
// Player
|
||||
|
||||
@@ -25,24 +25,12 @@ export function switchNavMode(mode) {
|
||||
document.getElementById('bnav-tab-discover')?.classList.toggle('active', mode==='discover');
|
||||
}
|
||||
|
||||
// ─── MOBILE SEARCH ───
|
||||
// ─── MOBILE SEARCH (legacy stubs — header search is now always visible) ───
|
||||
export function toggleMobileSearch() {
|
||||
const bar = document.getElementById('mobile-search-bar');
|
||||
const btn = document.getElementById('mobile-search-btn');
|
||||
const open = bar.style.display==='none' || bar.style.display==='';
|
||||
bar.style.display = open ? 'block' : 'none';
|
||||
btn.style.color = open ? 'var(--accent)' : 'var(--text2)';
|
||||
if(open) { setTimeout(() => document.getElementById('mobile-search-input').focus(), 50); }
|
||||
else { closeMobileSearch(); }
|
||||
document.getElementById('header-search-input')?.focus();
|
||||
}
|
||||
export function closeMobileSearch() {
|
||||
const bar = document.getElementById('mobile-search-bar');
|
||||
const inp = document.getElementById('mobile-search-input');
|
||||
const btn = document.getElementById('mobile-search-btn');
|
||||
bar.style.display = 'none';
|
||||
btn.style.color = 'var(--text2)';
|
||||
inp.value = '';
|
||||
navigate('home');
|
||||
import('./views.js').then(m => m.closeHeaderSearch());
|
||||
}
|
||||
|
||||
// ─── SETUP ───
|
||||
|
||||
+26
-8
@@ -27,7 +27,18 @@ export function _navLoad() {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function closeHeaderSearch() {
|
||||
const overlay = document.getElementById('header-search-overlay');
|
||||
const input = document.getElementById('header-search-input');
|
||||
const clearBtn = document.getElementById('header-search-clear');
|
||||
if (overlay) overlay.style.display = 'none';
|
||||
if (input) input.value = '';
|
||||
if (clearBtn) clearBtn.style.display = 'none';
|
||||
clearTimeout(S._headerSearchTimer);
|
||||
}
|
||||
|
||||
export function navigate(page, data=null) {
|
||||
closeHeaderSearch();
|
||||
document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
|
||||
document.querySelectorAll('.nav-item,.bnav-item').forEach(n => n.classList.remove('active','active-blue'));
|
||||
const cls = ['discover','new-releases','recommendations','spotify-importer'].includes(page) ? 'active-blue' : 'active';
|
||||
@@ -940,8 +951,8 @@ export function onLocalSearch(val) {
|
||||
S.searchTimer = setTimeout(() => doLocalSearch(val), 350);
|
||||
}
|
||||
|
||||
export async function doLocalSearch(q) {
|
||||
const el = document.getElementById('search-results');
|
||||
export async function doLocalSearch(q, el) {
|
||||
if (!el) el = document.getElementById('search-results');
|
||||
el.innerHTML = '<div class="spinner"></div>';
|
||||
try {
|
||||
const hiragana = await _romajiToHiragana(q);
|
||||
@@ -999,14 +1010,21 @@ export async function doLocalSearch(q) {
|
||||
} catch(e) { el.innerHTML = `<p style="color:var(--danger)">${e.message}</p>`; }
|
||||
}
|
||||
|
||||
// ─── MOBILE SEARCH ───
|
||||
export function onMobileSearch(val) {
|
||||
clearTimeout(S._mobileSearchTimer);
|
||||
if(!val.trim()) { navigate('home'); return; }
|
||||
navigate('search');
|
||||
S._mobileSearchTimer = setTimeout(() => doLocalSearch(val), 300);
|
||||
// ─── HEADER SEARCH (persistent inline bar) ───
|
||||
export function onHeaderSearch(val) {
|
||||
const overlay = document.getElementById('header-search-overlay');
|
||||
const clearBtn = document.getElementById('header-search-clear');
|
||||
if (clearBtn) clearBtn.style.display = val ? 'block' : 'none';
|
||||
clearTimeout(S._headerSearchTimer);
|
||||
if (!val.trim()) { if (overlay) overlay.style.display = 'none'; return; }
|
||||
if (overlay) overlay.style.display = 'block';
|
||||
const el = document.getElementById('header-search-results');
|
||||
S._headerSearchTimer = setTimeout(() => doLocalSearch(val, el), 300);
|
||||
}
|
||||
|
||||
// ─── MOBILE SEARCH (legacy no-op — replaced by inline header search) ───
|
||||
export function onMobileSearch(val) { onHeaderSearch(val); }
|
||||
|
||||
// ─── GLOBAL (ITUNES) SEARCH ───
|
||||
export function onGlobalSearch(val) {
|
||||
clearTimeout(S.globalSearchTimer);
|
||||
|
||||
Reference in new issue
Block a user