-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAppShell.tsx
More file actions
103 lines (94 loc) · 3.17 KB
/
AppShell.tsx
File metadata and controls
103 lines (94 loc) · 3.17 KB
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
import { Outlet } from "react-router-dom";
import { Box, Flex, Link } from "@chakra-ui/react";
import { Suspense } from "react";
import { TopBar } from "./TopBar";
import { Sidebar } from "./Sidebar.tsx";
import { ErrorBoundary } from "./ErrorBoundary.tsx";
import type { AuthUserLike } from "../types";
import { useBootstrapTaskStore } from "../hooks/useBootstrapTaskStore";
import { useBootstrapUserProfile } from "../hooks/useBootstrapUserProfile";
import { BottomBar } from "./BottomBar";
import { PublicSidebar } from "./PublicSidebar.tsx";
import { BasicSpinner } from "../components/ui/BasicSpinner";
import { Toaster } from "../components/ui/Toaster";
import { StorageDisclosureBanner } from "../components/ui/StorageDisclosureBanner";
import { DemoTourModal } from "../components/ui/DemoTourModal";
import { WelcomeModal } from "../components/ui/WelcomeModal";
const TOPBAR_H = "64px";
const BOTTOMBAR_H = "52px";
export function AppShell({
user,
onSignOut,
signedIn,
authLoading,
}: {
user?: AuthUserLike | null;
onSignOut?: () => void;
signedIn: boolean;
authLoading: boolean;
}) {
useBootstrapUserProfile(user);
useBootstrapTaskStore({ enabled: signedIn, authKey: user?.username || user?.userId || null });
return (
<Flex direction="column" h="100vh" bg="gray.50" overflow={"hidden"} className="AppShell" position="relative">
<Link
href="#main-content"
position="absolute"
left={2}
top={2}
px={3}
py={2}
bg="white"
borderWidth="1px"
borderColor="blue.200"
rounded="md"
boxShadow="sm"
zIndex={9999}
transform="translateY(-200%)"
_focusVisible={{ transform: "translateY(0)", outline: "2px solid", outlineColor: "blue.400" }}
>
Skip to content
</Link>
<Toaster />
<WelcomeModal signedIn={signedIn && !authLoading} />
<DemoTourModal signedIn={signedIn && !authLoading} />
{/* Top Bar stays fixed at the top */}
<Box h={TOPBAR_H} flexShrink={0}>
<TopBar user={user} />
</Box>
{/* Body: sidebar + main */}
<Flex flex="1" minH={0} overflow={"hidden"}>
{/* Sidebar stays visible, its own scroll if needed */}
<Box
flexShrink={0}
h="100%"
overflowY="auto"
borderRightWidth="1px"
>
{authLoading ? (
<Box w={"25vh"} h="100%">
<BasicSpinner height="100%" width="100%" size="md" />
</Box>
) : signedIn ? (
<Sidebar />
) : (
<PublicSidebar />
)}
</Box>
{/* Main area is the primary scroll container */}
<Box flex="1" minW={0} h="100%" overflow="auto" className="Main" id="main-content" tabIndex={-1}>
<ErrorBoundary title="Page Crashed">
<Suspense fallback={<BasicSpinner />}>
<Outlet />
</Suspense>
</ErrorBoundary>
</Box>
</Flex>
<StorageDisclosureBanner />
{/* Bottom Bar stays fixed at the bottom */}
<Box h={BOTTOMBAR_H} flexShrink={0}>
<BottomBar signedIn={signedIn} onSignOut={onSignOut} />
</Box>
</Flex>
);
}