Spaces:
Runtime error
Runtime error
File size: 4,378 Bytes
cd8bd0a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | "use client";
import { Suspense, useEffect, useState } from "react";
import Sidebar from "../Sidebar";
import Header from "../Header";
import NotificationToast from "../NotificationToast";
import Breadcrumbs from "../Breadcrumbs";
import MaintenanceBanner from "../MaintenanceBanner";
import CommandPalette from "../CommandPalette";
import NavigationProgress from "../NavigationProgress";
import { useIsElectron } from "@/shared/hooks/useElectron";
const SIDEBAR_COLLAPSED_KEY = "sidebar-collapsed";
const isE2EMode = process.env.NEXT_PUBLIC_OMNIROUTE_E2E_MODE === "1";
export default function DashboardLayout({ children }) {
const [sidebarOpen, setSidebarOpen] = useState(false);
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
const isElectron = useIsElectron();
const [collapsed, setCollapsed] = useState(() => {
if (typeof globalThis.window === "undefined") return false;
try {
return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "true";
} catch {
return false;
}
});
const isMacElectron =
isElectron &&
typeof globalThis.window !== "undefined" &&
globalThis.electronAPI?.platform === "darwin";
useEffect(() => {
if (typeof document === "undefined") return;
document.body.classList.toggle("electron-macos", isMacElectron);
return () => {
document.body.classList.remove("electron-macos");
};
}, [isMacElectron]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
e.preventDefault();
setCommandPaletteOpen((prev) => !prev);
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, []);
const handleToggleCollapse = () => {
const next = !collapsed;
setCollapsed(next);
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, String(next));
};
return (
// No bg-bg here: the body grid wallpaper (globals.css body::before) shows through
// this transparent wrapper into the content area. body's --color-bg is the base fill.
<div className="flex h-dvh min-h-0 w-full overflow-hidden">
<Suspense fallback={null}>
<NavigationProgress />
</Suspense>
{/* Mobile sidebar overlay */}
{sidebarOpen && (
<div
className="fixed inset-0 z-40 bg-black/20 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}
{/* Sidebar - Desktop: keep visibility independent from Tailwind hidden/lg:flex ordering. */}
<div className="dashboard-sidebar-desktop">
<Sidebar
collapsed={collapsed}
onToggleCollapse={handleToggleCollapse}
isMacElectron={isMacElectron}
/>
</div>
{/* Sidebar - Mobile: full viewport height with proper scroll containment */}
<div
className={`fixed inset-y-0 start-0 z-50 transform lg:hidden transition-transform duration-300 ease-in-out h-dvh overflow-y-auto ${
sidebarOpen ? "translate-x-0" : "-translate-x-full"
}`}
>
<Sidebar onClose={() => setSidebarOpen(false)} isMacElectron={isMacElectron} />
</div>
{/* Main content */}
<main
id="main-content"
className="relative flex min-h-0 flex-1 min-w-0 flex-col transition-colors duration-300"
>
<Header
onMenuClick={() => setSidebarOpen(true)}
onOpenCommandPalette={() => setCommandPaletteOpen(true)}
/>
{!isE2EMode && <MaintenanceBanner />}
<div className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden custom-scrollbar p-4 sm:p-6 lg:p-10">
{/* Fluid up to a 4K cap (3840px): content follows the viewport on large
monitors and only centers (side gutters) beyond ~4K, instead of the prior
1280px cap that left big empty margins on wide screens. */}
<div className="max-w-[3840px] mx-auto w-full h-full min-h-0 flex flex-col">
<Breadcrumbs />
<div className="flex-1 min-h-0">
{children}
</div>
</div>
</div>
</main>
{/* Global notification toast system */}
<NotificationToast />
<CommandPalette isOpen={commandPaletteOpen} onClose={() => setCommandPaletteOpen(false)} />
</div>
);
}
|