71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
|
|
|
export const DRAWER_WIDTH = 240;
|
|
export const DRAWER_WIDTH_COLLAPSED = 64;
|
|
|
|
interface LayoutContextType {
|
|
sidebarCollapsed: boolean;
|
|
chatPanelOpen: boolean;
|
|
toggleSidebar: () => void;
|
|
toggleChatPanel: () => void;
|
|
setChatPanelOpen: (open: boolean) => void;
|
|
}
|
|
|
|
const LayoutContext = createContext<LayoutContextType | undefined>(undefined);
|
|
|
|
function getInitialCollapsed(): boolean {
|
|
try {
|
|
const stored = localStorage.getItem('sidebar-collapsed');
|
|
return stored === 'true';
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
interface LayoutProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export const LayoutProvider: React.FC<LayoutProviderProps> = ({ children }) => {
|
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(getInitialCollapsed);
|
|
const [chatPanelOpen, setChatPanelOpenState] = useState(false);
|
|
|
|
const toggleSidebar = useCallback(() => {
|
|
setSidebarCollapsed((prev) => {
|
|
const next = !prev;
|
|
try {
|
|
localStorage.setItem('sidebar-collapsed', String(next));
|
|
} catch {
|
|
// ignore storage errors
|
|
}
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const toggleChatPanel = useCallback(() => {
|
|
setChatPanelOpenState((prev) => !prev);
|
|
}, []);
|
|
|
|
const setChatPanelOpen = useCallback((open: boolean) => {
|
|
setChatPanelOpenState(open);
|
|
}, []);
|
|
|
|
const value: LayoutContextType = {
|
|
sidebarCollapsed,
|
|
chatPanelOpen,
|
|
toggleSidebar,
|
|
toggleChatPanel,
|
|
setChatPanelOpen,
|
|
};
|
|
|
|
return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>;
|
|
};
|
|
|
|
export const useLayout = (): LayoutContextType => {
|
|
const context = useContext(LayoutContext);
|
|
if (context === undefined) {
|
|
throw new Error('useLayout must be used within a LayoutProvider');
|
|
}
|
|
return context;
|
|
};
|