mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 10:51:02 +01:00
feat(sidebar): implement collapsible sidebar functionality with localStorage support
This commit is contained in:
36
src/lib/client/stores/sidebar.ts
Normal file
36
src/lib/client/stores/sidebar.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
const STORAGE_KEY = 'sidebar-collapsed';
|
||||
|
||||
function createSidebarStore() {
|
||||
// Get initial value from localStorage
|
||||
const initial = browser ? localStorage.getItem(STORAGE_KEY) === 'true' : false;
|
||||
const { subscribe, set, update } = writable(initial);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
toggle: () =>
|
||||
update((collapsed) => {
|
||||
const newValue = !collapsed;
|
||||
if (browser) {
|
||||
localStorage.setItem(STORAGE_KEY, String(newValue));
|
||||
}
|
||||
return newValue;
|
||||
}),
|
||||
collapse: () => {
|
||||
set(true);
|
||||
if (browser) {
|
||||
localStorage.setItem(STORAGE_KEY, 'true');
|
||||
}
|
||||
},
|
||||
expand: () => {
|
||||
set(false);
|
||||
if (browser) {
|
||||
localStorage.setItem(STORAGE_KEY, 'false');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const sidebarCollapsed = createSidebarStore();
|
||||
@@ -2,10 +2,13 @@
|
||||
import AccentPicker from './accentPicker.svelte';
|
||||
import ThemeToggle from './themeToggle.svelte';
|
||||
import logo from '$assets/logo-firefox-circular-arrow.png';
|
||||
|
||||
export let collapsed: boolean = false;
|
||||
</script>
|
||||
|
||||
<nav
|
||||
class="fixed top-0 left-0 z-50 w-72 border-b border-r border-neutral-200 bg-neutral-50 dark:border-neutral-800 dark:bg-neutral-900"
|
||||
class="fixed top-0 left-0 z-50 w-72 border-b border-r border-neutral-200 bg-neutral-50 transition-transform duration-200 dark:border-neutral-800 dark:bg-neutral-900"
|
||||
class:-translate-x-[calc(100%-24px)]={collapsed}
|
||||
>
|
||||
<div class="flex items-center justify-between px-4 py-4">
|
||||
<!-- Left: Brand name with logo -->
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
import Group from './group.svelte';
|
||||
import GroupItem from './groupItem.svelte';
|
||||
import Version from './version.svelte';
|
||||
|
||||
export let collapsed: boolean = false;
|
||||
</script>
|
||||
|
||||
<nav
|
||||
class="fixed top-16 left-0 flex h-[calc(100vh-4rem)] w-72 flex-col border-r border-neutral-200 bg-neutral-50 dark:border-neutral-800 dark:bg-neutral-900"
|
||||
class="fixed top-16 left-0 flex h-[calc(100vh-4rem)] w-72 flex-col border-r border-neutral-200 bg-neutral-50 transition-transform duration-200 dark:border-neutral-800 dark:bg-neutral-900"
|
||||
class:-translate-x-[calc(100%-24px)]={collapsed}
|
||||
>
|
||||
<div class="flex-1 overflow-y-auto p-4">
|
||||
<Group label="🏠 Home" href="/" hasItems={true}>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import Navbar from '$ui/navigation/navbar/navbar.svelte';
|
||||
import PageNav from '$ui/navigation/pageNav/pageNav.svelte';
|
||||
import AlertContainer from '$alerts/AlertContainer.svelte';
|
||||
import { sidebarCollapsed } from '$lib/client/stores/sidebar';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -11,10 +12,25 @@
|
||||
<title>Profilarr</title>
|
||||
</svelte:head>
|
||||
|
||||
<Navbar />
|
||||
<PageNav />
|
||||
<Navbar collapsed={$sidebarCollapsed} />
|
||||
<PageNav collapsed={$sidebarCollapsed} />
|
||||
<AlertContainer />
|
||||
|
||||
<main class="pl-72">
|
||||
<!-- Sidebar collapse toggle button -->
|
||||
<button
|
||||
type="button"
|
||||
on:click={() => sidebarCollapsed.toggle()}
|
||||
class="fixed top-16 z-50 flex h-6 w-6 -translate-x-1/2 -translate-y-1/3 items-center justify-center rounded-md border border-neutral-300 bg-white shadow-sm transition-all hover:bg-neutral-50 dark:border-neutral-700 dark:bg-neutral-800 dark:hover:bg-neutral-700"
|
||||
style="left: {$sidebarCollapsed ? '24px' : '288px'}"
|
||||
aria-label={$sidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
||||
>
|
||||
<div class="flex flex-col gap-[3px]">
|
||||
<div class="h-[2px] w-3 rounded-full bg-neutral-400 dark:bg-neutral-500"></div>
|
||||
<div class="h-[2px] w-3 rounded-full bg-neutral-400 dark:bg-neutral-500"></div>
|
||||
<div class="h-[2px] w-3 rounded-full bg-neutral-400 dark:bg-neutral-500"></div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<main class="transition-all duration-200 {$sidebarCollapsed ? 'pl-[24px]' : 'pl-72'}">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user