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:
@@ -96,3 +96,10 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* App shell main content responsive margin */
|
||||
@media (min-width: 768px) {
|
||||
.app-shell-main {
|
||||
margin-left: var(--current-sidebar-width, var(--sidebar-width));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,45 @@
|
||||
export default function Home() {
|
||||
'use client';
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { AppShell } from '@/components/layout/app-shell';
|
||||
|
||||
export default function DashboardPage() {
|
||||
const t = useTranslations('dashboard');
|
||||
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-center">
|
||||
<h1 className="text-4xl font-bold">Tessera</h1>
|
||||
<p className="mt-4 text-lg text-gray-600">
|
||||
Portal wird geladen...
|
||||
</p>
|
||||
</main>
|
||||
<AppShell>
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] gap-4">
|
||||
{/* Grid icon */}
|
||||
<div className="rounded-lg bg-muted p-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<rect x="3" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="14" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="14" y="14" width="7" height="7" rx="1" />
|
||||
<rect x="3" y="14" width="7" height="7" rx="1" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Empty state text (D-16) */}
|
||||
<p className="text-lg text-muted-foreground">
|
||||
{t('empty')}
|
||||
</p>
|
||||
|
||||
{/* Add widget button */}
|
||||
<button className="mt-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 transition-opacity">
|
||||
{t('addWidget')}
|
||||
</button>
|
||||
</div>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user