diff --git a/app/layout.tsx b/app/layout.tsx
index 20cbed2..17c3243 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,6 +1,12 @@
import './globals.css';
import type { Metadata, Viewport } from 'next';
+import { cookies } from 'next/headers';
+import { SidebarPreferenceProvider } from '@/components/providers/sidebar-preference-provider';
import { QueryProvider } from '@/components/providers/query-provider';
+import {
+ SIDEBAR_PREFERENCE_KEY,
+ parseSidebarPreference
+} from '@/lib/sidebar-preference';
export const metadata: Metadata = {
title: 'Fiscal Clone',
@@ -14,11 +20,18 @@ export const viewport: Viewport = {
themeColor: '#121417'
};
-export default function RootLayout({ children }: { children: React.ReactNode }) {
+export default async function RootLayout({ children }: { children: React.ReactNode }) {
+ const cookieStore = await cookies();
+ const initialSidebarCollapsed = parseSidebarPreference(
+ cookieStore.get(SIDEBAR_PREFERENCE_KEY)?.value
+ );
+
return (
- {children}
+
+ {children}
+
);
diff --git a/components/providers/sidebar-preference-provider.tsx b/components/providers/sidebar-preference-provider.tsx
new file mode 100644
index 0000000..c0a6596
--- /dev/null
+++ b/components/providers/sidebar-preference-provider.tsx
@@ -0,0 +1,32 @@
+'use client';
+
+import { createContext, useContext } from 'react';
+
+type SidebarPreferenceContextValue = {
+ initialSidebarCollapsed: boolean;
+};
+
+const SidebarPreferenceContext =
+ createContext({
+ initialSidebarCollapsed: false
+ });
+
+type SidebarPreferenceProviderProps = {
+ children: React.ReactNode;
+ initialSidebarCollapsed: boolean;
+};
+
+export function SidebarPreferenceProvider({
+ children,
+ initialSidebarCollapsed
+}: SidebarPreferenceProviderProps) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function useSidebarPreference() {
+ return useContext(SidebarPreferenceContext);
+}
diff --git a/components/shell/app-shell.tsx b/components/shell/app-shell.tsx
index 0be6fc7..6139adc 100644
--- a/components/shell/app-shell.tsx
+++ b/components/shell/app-shell.tsx
@@ -23,6 +23,7 @@ import { useEffect, useMemo, useState } from "react";
import { authClient } from "@/lib/auth-client";
import { TaskDetailModal } from "@/components/notifications/task-detail-modal";
import { TaskNotificationsTrigger } from "@/components/notifications/task-notifications-trigger";
+import { useSidebarPreference } from "@/components/providers/sidebar-preference-provider";
import {
companyAnalysisQueryOptions,
companyFinancialStatementsQueryOptions,
@@ -37,6 +38,7 @@ import { buildGraphingHref } from "@/lib/graphing/catalog";
import type { ActiveContext, NavGroup, NavItem } from "@/lib/types";
import { Button } from "@/components/ui/button";
import { useTaskNotificationsCenter } from "@/hooks/use-task-notifications-center";
+import { SIDEBAR_PREFERENCE_KEY } from "@/lib/sidebar-preference";
import { cn } from "@/lib/utils";
type AppShellProps = {
@@ -148,8 +150,6 @@ const GROUP_LABELS: Record = {
portfolio: "Portfolio",
};
-const SIDEBAR_PREFERENCE_KEY = "fiscal-shell-sidebar-collapsed";
-
function normalizeTicker(value: string | null | undefined) {
const normalized = value?.trim().toUpperCase() ?? "";
return normalized.length > 0 ? normalized : null;
@@ -260,12 +260,16 @@ export function AppShell({
const router = useRouter();
const searchParams = useSearchParams();
const queryClient = useQueryClient();
+ const { initialSidebarCollapsed } = useSidebarPreference();
const [isSigningOut, setIsSigningOut] = useState(false);
const [isMoreOpen, setIsMoreOpen] = useState(false);
- const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
- const [hasLoadedSidebarPreference, setHasLoadedSidebarPreference] =
+ const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(
+ initialSidebarCollapsed,
+ );
+ const [hasResolvedSidebarPreference, setHasResolvedSidebarPreference] =
useState(false);
+ const [hasMounted, setHasMounted] = useState(false);
const notifications = useTaskNotificationsCenter();
const { data: session } = authClient.useSession();
const sessionUser = (session?.user ?? null) as {
@@ -433,14 +437,14 @@ export function AppShell({
const storedPreference = window.localStorage.getItem(
SIDEBAR_PREFERENCE_KEY,
);
- if (storedPreference === "true") {
- setIsSidebarCollapsed(true);
+ if (storedPreference === "true" || storedPreference === "false") {
+ setIsSidebarCollapsed(storedPreference === "true");
}
- setHasLoadedSidebarPreference(true);
+ setHasResolvedSidebarPreference(true);
}, []);
useEffect(() => {
- if (!hasLoadedSidebarPreference) {
+ if (!hasResolvedSidebarPreference) {
return;
}
@@ -448,7 +452,12 @@ export function AppShell({
SIDEBAR_PREFERENCE_KEY,
String(isSidebarCollapsed),
);
- }, [hasLoadedSidebarPreference, isSidebarCollapsed]);
+ document.cookie = `${SIDEBAR_PREFERENCE_KEY}=${String(isSidebarCollapsed)}; path=/; max-age=31536000; samesite=lax`;
+ }, [hasResolvedSidebarPreference, isSidebarCollapsed]);
+
+ useEffect(() => {
+ setHasMounted(true);
+ }, []);
useEffect(() => {
const browserWindow = window as Window & {
@@ -520,7 +529,8 @@ export function AppShell({
>