Organize/components/nav/side-nav-provider.tsx

45 lines
1.2 KiB
TypeScript

"use client";
import { createContext, useContext, useEffect, useState } from "react";
const STORAGE_KEY = "organize:sidenav-collapsed";
interface SideNavContextValue {
collapsed: boolean;
toggle: () => void;
}
const SideNavContext = createContext<SideNavContextValue | null>(null);
export function SideNavProvider({ children }: { children: React.ReactNode }) {
// Default expanded on both server and first client render to avoid a
// hydration mismatch; the real persisted value is applied right after
// mount, trading a one-frame flash for zero hydration warnings.
const [collapsed, setCollapsed] = useState(false);
useEffect(() => {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored !== null) setCollapsed(stored === "true");
}, []);
const toggle = () => {
setCollapsed((prev) => {
const next = !prev;
localStorage.setItem(STORAGE_KEY, String(next));
return next;
});
};
return (
<SideNavContext.Provider value={{ collapsed, toggle }}>
{children}
</SideNavContext.Provider>
);
}
export function useSideNav() {
const ctx = useContext(SideNavContext);
if (!ctx) throw new Error("useSideNav must be used within a SideNavProvider");
return ctx;
}