Make sidebar collapsible with hamburger toggle
Sidebar is now hidden by default, opened via a small hamburger button in the top-left corner. Clicking a nav link or the overlay closes it. Keeps focus on the search bar. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,19 +3,56 @@
|
||||
import { page } from '$app/stores';
|
||||
let { children } = $props();
|
||||
|
||||
let sidebarOpen = $state(false);
|
||||
|
||||
function isActive(path) {
|
||||
const current = $page.url.pathname;
|
||||
if (path === '/') return current === '/';
|
||||
return current.startsWith(path);
|
||||
}
|
||||
|
||||
function closeSidebar() {
|
||||
sidebarOpen = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex h-screen overflow-hidden">
|
||||
<div class="relative h-screen overflow-hidden">
|
||||
<!-- Hamburger toggle -->
|
||||
<button
|
||||
onclick={() => sidebarOpen = !sidebarOpen}
|
||||
class="fixed top-3 left-3 z-50 w-8 h-8 flex items-center justify-center rounded
|
||||
bg-surface-raised/80 backdrop-blur border border-surface-border
|
||||
hover:bg-surface-hover hover:border-surface-border-hover
|
||||
text-text-secondary hover:text-text-primary transition-all duration-150"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
{#if sidebarOpen}
|
||||
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5M3.75 17.25h16.5" />
|
||||
</svg>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Overlay -->
|
||||
{#if sidebarOpen}
|
||||
<button
|
||||
class="fixed inset-0 z-30 bg-black/50 backdrop-blur-sm"
|
||||
onclick={closeSidebar}
|
||||
aria-label="Close menu"
|
||||
></button>
|
||||
{/if}
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-56 flex-shrink-0 bg-surface border-r border-surface-border flex flex-col">
|
||||
<aside class="fixed top-0 left-0 z-40 h-full w-56 bg-surface border-r border-surface-border flex flex-col
|
||||
transform transition-transform duration-200 ease-out
|
||||
{sidebarOpen ? 'translate-x-0' : '-translate-x-full'}">
|
||||
<!-- Logo -->
|
||||
<div class="px-4 py-4 border-b border-surface-border">
|
||||
<a href="/" class="flex items-center gap-2.5 group">
|
||||
<a href="/" onclick={closeSidebar} class="flex items-center gap-2.5 group">
|
||||
<div class="w-6 h-6 rounded bg-accent flex items-center justify-center">
|
||||
<svg class="w-3.5 h-3.5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
|
||||
@@ -28,14 +65,14 @@
|
||||
<!-- Nav -->
|
||||
<nav class="flex-1 px-2 py-3 space-y-0.5 overflow-y-auto">
|
||||
<span class="block px-2 py-1.5 text-2xs font-medium text-text-tertiary uppercase tracking-wider">Search</span>
|
||||
<a href="/" class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
<a href="/" onclick={closeSidebar} class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
{isActive('/') && !isActive('/results') && !isActive('/admin') ? 'bg-surface-hover text-text-primary' : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover'}">
|
||||
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
|
||||
</svg>
|
||||
Search
|
||||
</a>
|
||||
<a href="/results?q=" class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
<a href="/results?q=" onclick={closeSidebar} class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
{isActive('/results') ? 'bg-surface-hover text-text-primary' : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover'}">
|
||||
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||
@@ -44,14 +81,14 @@
|
||||
</a>
|
||||
|
||||
<span class="block px-2 pt-4 pb-1.5 text-2xs font-medium text-text-tertiary uppercase tracking-wider">Manage</span>
|
||||
<a href="/admin" class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
<a href="/admin" onclick={closeSidebar} class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
{isActive('/admin') && !isActive('/admin/categories') ? 'bg-surface-hover text-text-primary' : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover'}">
|
||||
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 21v-7.5a.75.75 0 01.75-.75h3a.75.75 0 01.75.75V21m-4.5 0H2.36m11.14 0H18m0 0h3.64m-1.39 0V9.349m-16.5 11.65V9.35m0 0a3.001 3.001 0 003.75-.615A2.993 2.993 0 009.75 9.75c.896 0 1.7-.393 2.25-1.016a2.993 2.993 0 002.25 1.016c.896 0 1.7-.393 2.25-1.016A3.001 3.001 0 0021 9.349m-18 0a2.997 2.997 0 00.177-.728C3.364 7.364 4 6 4.5 4.5h15c.5 1.5 1.136 2.864 1.323 3.621a2.997 2.997 0 00.177.728" />
|
||||
</svg>
|
||||
Stores
|
||||
</a>
|
||||
<a href="/admin/categories" class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
<a href="/admin/categories" onclick={closeSidebar} class="flex items-center gap-2.5 px-2 py-1.5 rounded text-sm transition-colors duration-100
|
||||
{isActive('/admin/categories') ? 'bg-surface-hover text-text-primary' : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover'}">
|
||||
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" />
|
||||
@@ -62,8 +99,8 @@
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Main content -->
|
||||
<main class="flex-1 overflow-y-auto bg-surface">
|
||||
<!-- Main content (full width) -->
|
||||
<main class="h-full overflow-y-auto bg-surface">
|
||||
{@render children()}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user