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:
1 parent
75aab4edb5
commit
442794fa81
1 file changed
+45
-5
@@ -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(() => {
|
onMount(() => {
|
||||||
loadSortPreference();
|
loadSortPreference();
|
||||||
loadUserPlaylists();
|
loadUserPlaylists();
|
||||||
@@ -723,6 +759,7 @@
|
|||||||
loadLocalTrackCounts();
|
loadLocalTrackCounts();
|
||||||
loadFolders(); // Load playlist folders
|
loadFolders(); // Load playlist folders
|
||||||
loadFavoritesPreferences(); // Load favorites tab order
|
loadFavoritesPreferences(); // Load favorites tab order
|
||||||
|
loadSidebarCollapseState(); // Load collapse states
|
||||||
|
|
||||||
// Subscribe to offline state changes
|
// Subscribe to offline state changes
|
||||||
const unsubscribeOffline = subscribeOffline(() => {
|
const unsubscribeOffline = subscribeOffline(() => {
|
||||||
@@ -1013,14 +1050,17 @@
|
|||||||
<Heart size={14} />
|
<Heart size={14} />
|
||||||
</div>
|
</div>
|
||||||
<span class="label">{$t('nav.favorites')}</span>
|
<span class="label">{$t('nav.favorites')}</span>
|
||||||
<button
|
<span
|
||||||
class="favorites-chevron"
|
class="favorites-chevron"
|
||||||
class:expanded={favoritesExpanded}
|
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'}
|
title={favoritesExpanded ? 'Collapse' : 'Expand'}
|
||||||
>
|
>
|
||||||
<ChevronRight size={12} />
|
<ChevronRight size={12} />
|
||||||
</button>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{#if favoritesExpanded}
|
{#if favoritesExpanded}
|
||||||
<div class="favorites-subitems">
|
<div class="favorites-subitems">
|
||||||
@@ -1110,7 +1150,7 @@
|
|||||||
>
|
>
|
||||||
<MoreHorizontal size={14} />
|
<MoreHorizontal size={14} />
|
||||||
</button>
|
</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}
|
{#if playlistsCollapsed}
|
||||||
<ChevronDown size={14} />
|
<ChevronDown size={14} />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -1290,7 +1330,7 @@
|
|||||||
<!-- Local Library Section -->
|
<!-- Local Library Section -->
|
||||||
<div class="section local-library-section">
|
<div class="section local-library-section">
|
||||||
{#if isExpanded}
|
{#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>
|
<span class="section-header">{$t('library.title')}</span>
|
||||||
{#if localLibraryCollapsed}
|
{#if localLibraryCollapsed}
|
||||||
<ChevronDown size={12} />
|
<ChevronDown size={12} />
|
||||||
|
|||||||
Reference in new issue
Block a user