(front) add LeftPanelContext for mobile panel state

Introduce a context to manage left panel visibility on
mobile, integrate it into SimpleLayout and calendar page.
This commit is contained in:
Nathan Panchout
2026-03-11 10:43:20 +01:00
parent 75f26b59d2
commit e7446788f2
4 changed files with 65 additions and 4 deletions

View File

@@ -3,6 +3,7 @@ import { GlobalLayout } from "../global/GlobalLayout";
import { HeaderRight } from "../header/Header";
import { Toaster } from "@/features/ui/components/toaster/Toaster";
import { LeftPanelMobile } from "@/features/layouts/components/left-panel/LeftPanelMobile";
import { useLeftPanel } from "../../contexts/LeftPanelContext";
export const getSimpleLayout = (page: React.ReactElement) => {
return <SimpleLayout>{page}</SimpleLayout>;
@@ -14,12 +15,15 @@ export const getSimpleLayout = (page: React.ReactElement) => {
* Auth context to the children.
*/
export const SimpleLayout = ({ children }: { children: React.ReactNode }) => {
const { isLeftPanelOpen, setIsLeftPanelOpen } = useLeftPanel();
return (
<div>
<GlobalLayout>
<MainLayout
enableResize
hideLeftPanelOnDesktop={true}
isLeftPanelOpen={isLeftPanelOpen}
setIsLeftPanelOpen={setIsLeftPanelOpen}
leftPanelContent={<LeftPanelMobile />}
rightHeaderContent={<HeaderRight />}
>

View File

@@ -0,0 +1,45 @@
import {
createContext,
useContext,
useMemo,
useState,
type ReactNode,
} from "react";
interface LeftPanelContextType {
isLeftPanelOpen: boolean;
setIsLeftPanelOpen: (open: boolean) => void;
}
const LeftPanelContext = createContext<LeftPanelContextType | undefined>(
undefined,
);
export const useLeftPanel = () => {
const context = useContext(LeftPanelContext);
if (!context) {
throw new Error(
"useLeftPanel must be used within a LeftPanelProvider",
);
}
return context;
};
interface LeftPanelProviderProps {
children: ReactNode;
}
export const LeftPanelProvider = ({ children }: LeftPanelProviderProps) => {
const [isLeftPanelOpen, setIsLeftPanelOpen] = useState(false);
const value = useMemo(
() => ({ isLeftPanelOpen, setIsLeftPanelOpen }),
[isLeftPanelOpen, setIsLeftPanelOpen],
);
return (
<LeftPanelContext.Provider value={value}>
{children}
</LeftPanelContext.Provider>
);
};

View File

@@ -33,6 +33,7 @@ import {
} from "@/features/ui/cunningham/useCunninghamTheme";
import { FeedbackFooterMobile } from "@/features/feedback/Feedback";
import { useDynamicFavicon } from "@/features/ui/hooks/useDynamicFavicon";
import { LeftPanelProvider } from "@/features/layouts/contexts/LeftPanelContext";
export type NextPageWithLayout<P = object, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode;
@@ -134,8 +135,10 @@ const MyAppInner = ({ Component, pageProps }: AppPropsWithLayout) => {
<ConfigProvider>
<AnalyticsProvider>
<LeftPanelProvider>
{getLayout(<Component {...pageProps} />)}
<FeedbackFooterMobile />
</LeftPanelProvider>
</AnalyticsProvider>
</ConfigProvider>

View File

@@ -15,6 +15,7 @@ import {
HeaderIcon,
HeaderRight,
} from "@/features/layouts/components/header/Header";
import { useLeftPanel } from "@/features/layouts/contexts/LeftPanelContext";
import { SpinnerPage } from "@/features/ui/components/spinner/SpinnerPage";
import { Toaster } from "@/features/ui/components/toaster/Toaster";
import { Scheduler } from "@/features/calendar/components/scheduler/Scheduler";
@@ -56,7 +57,9 @@ export default function CalendarPage() {
);
}
CalendarPage.getLayout = function getLayout(page: React.ReactElement) {
const CalendarLayout = ({ children }: { children: React.ReactNode }) => {
const { isLeftPanelOpen, setIsLeftPanelOpen } = useLeftPanel();
return (
<CalendarContextProvider>
<div className="calendars__calendar">
@@ -66,11 +69,17 @@ CalendarPage.getLayout = function getLayout(page: React.ReactElement) {
leftPanelContent={<LeftPanel />}
icon={<HeaderIcon />}
rightHeaderContent={<HeaderRight />}
isLeftPanelOpen={isLeftPanelOpen}
setIsLeftPanelOpen={setIsLeftPanelOpen}
>
{page}
{children}
</MainLayout>
</GlobalLayout>
</div>
</CalendarContextProvider>
);
};
CalendarPage.getLayout = function getLayout(page: React.ReactElement) {
return <CalendarLayout>{page}</CalendarLayout>;
};