fix(sidebar): button nesting and persist collapse state

- Change nested button to span with role="button" for favorites chevron
- Add localStorage persistence for collapse state of:
  - Favorites section (expanded/collapsed)
  - Playlists section (collapsed/expanded)
  - Local Library section (collapsed/expanded)
- Folder collapse state intentionally not persisted
This commit is contained in:
vicrodh committed 2026-01-30 00:12:12 -06:00
1 parent 75aab4edb5
commit 442794fa81
1 file changed
+45 -5
+45 -5
View File
@@ -716,6 +716,42 @@
}
}
// Sidebar collapse state persistence
const SIDEBAR_COLLAPSE_KEY = 'qbz-sidebar-collapse-state';
interface SidebarCollapseState {
favoritesExpanded: boolean;
playlistsCollapsed: boolean;
localLibraryCollapsed: boolean;
}
function loadSidebarCollapseState() {
try {
const stored = localStorage.getItem(SIDEBAR_COLLAPSE_KEY);
if (stored) {
const state: SidebarCollapseState = JSON.parse(stored);
favoritesExpanded = state.favoritesExpanded ?? false;
playlistsCollapsed = state.playlistsCollapsed ?? false;
localLibraryCollapsed = state.localLibraryCollapsed ?? false;
}
} catch (err) {
console.debug('[Sidebar] Failed to load collapse state:', err);
}
}
function saveSidebarCollapseState() {
try {
const state: SidebarCollapseState = {
favoritesExpanded,
playlistsCollapsed,
localLibraryCollapsed
};
localStorage.setItem(SIDEBAR_COLLAPSE_KEY, JSON.stringify(state));
} catch (err) {
console.debug('[Sidebar] Failed to save collapse state:', err);
}
}
onMount(() => {
loadSortPreference();
loadUserPlaylists();
@@ -723,6 +759,7 @@
loadLocalTrackCounts();
loadFolders(); // Load playlist folders
loadFavoritesPreferences(); // Load favorites tab order
loadSidebarCollapseState(); // Load collapse states
// Subscribe to offline state changes
const unsubscribeOffline = subscribeOffline(() => {
@@ -1013,14 +1050,17 @@
<Heart size={14} />
</div>
<span class="label">{$t('nav.favorites')}</span>
<button
<span
class="favorites-chevron"
class:expanded={favoritesExpanded}
onclick={(e) => { e.stopPropagation(); favoritesExpanded = !favoritesExpanded; }}
role="button"
tabindex="0"
onclick={(e) => { e.stopPropagation(); favoritesExpanded = !favoritesExpanded; saveSidebarCollapseState(); }}
onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.stopPropagation(); e.preventDefault(); favoritesExpanded = !favoritesExpanded; saveSidebarCollapseState(); }}}
title={favoritesExpanded ? 'Collapse' : 'Expand'}
>
<ChevronRight size={12} />
</button>
</span>
</button>
{#if favoritesExpanded}
<div class="favorites-subitems">
@@ -1110,7 +1150,7 @@
>
<MoreHorizontal size={14} />
</button>
<button class="icon-btn" onclick={() => playlistsCollapsed = !playlistsCollapsed} title={playlistsCollapsed ? $t('actions.open') : $t('actions.close')}>
<button class="icon-btn" onclick={() => { playlistsCollapsed = !playlistsCollapsed; saveSidebarCollapseState(); }} title={playlistsCollapsed ? $t('actions.open') : $t('actions.close')}>
{#if playlistsCollapsed}
<ChevronDown size={14} />
{:else}
@@ -1290,7 +1330,7 @@
<!-- Local Library Section -->
<div class="section local-library-section">
{#if isExpanded}
<button class="section-header-btn" onclick={() => localLibraryCollapsed = !localLibraryCollapsed}>
<button class="section-header-btn" onclick={() => { localLibraryCollapsed = !localLibraryCollapsed; saveSidebarCollapseState(); }}>
<span class="section-header">{$t('library.title')}</span>
{#if localLibraryCollapsed}
<ChevronDown size={12} />