feat(01-02): portal layout with header, sidebar, theme toggle, locale switcher
- Zustand sidebar store with persist middleware (collapse/expand, mobile open) - Sticky header with logo, breadcrumb, theme toggle, locale switcher, user avatar - Collapsible sidebar with Dashboard/Marketplace nav, accordion categories, footer - Mobile responsive: hamburger menu with overlay sidebar on small screens - Theme toggle cycling light/dark/system with mounted guard - Locale switcher setting NEXT_LOCALE cookie with router.refresh - Empty dashboard state with grid icon, "Keine Widgets aktiv" text, add button - AppShell composing header + sidebar + responsive main content area - All user-visible strings via useTranslations (UI-03 compliance)
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
||||
import { Header } from '@/components/layout/header';
|
||||
import { Sidebar } from '@/components/layout/sidebar';
|
||||
|
||||
export function AppShell({ children }: { children: React.ReactNode }) {
|
||||
const isCollapsed = useSidebarStore((s) => s.isCollapsed);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
// Desktop: sidebar pushes content via margin-left
|
||||
// Mobile: sidebar overlays, no margin needed (handled by app-shell-main class in globals.css)
|
||||
const sidebarWidth = isCollapsed
|
||||
? 'var(--sidebar-width-collapsed)'
|
||||
: 'var(--sidebar-width)';
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<Sidebar />
|
||||
<main
|
||||
className="app-shell-main min-h-[calc(100vh-var(--header-height))] transition-all duration-200 p-6"
|
||||
style={mounted ? { '--current-sidebar-width': sidebarWidth } as React.CSSProperties : undefined}
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user