import { LOCAL_STORAGE_KEYS, useBreakpoint, useParams } from 'common' import { useRouter } from 'next/router' import { PropsWithChildren, useEffect, useState } from 'react' import { ResizablePanel, ResizablePanelGroup, SidebarProvider } from 'ui' import { BannerStack } from '../ui/BannerStack/BannerStack' import { LayoutHeader } from './Navigation/LayoutHeader/LayoutHeader' import MobileNavigationBar from './Navigation/NavigationBar/MobileNavigationBar' import { MobileSheetProvider } from './Navigation/NavigationBar/MobileSheetContext' import { StudioMobileSheetNav } from './Navigation/NavigationBar/StudioMobileSheetNav' import { LayoutSidebar } from './ProjectLayout/LayoutSidebar' import { LayoutSidebarProvider } from './ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import { ProjectContextProvider } from './ProjectLayout/ProjectContext' import { AppBannerWrapper } from '@/components/interfaces/App/AppBannerWrapper' import { Sidebar } from '@/components/interfaces/Sidebar' import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' import { useCheckLatestDeploy } from '@/hooks/use-check-latest-deploy' import { IS_PLATFORM } from '@/lib/constants' import { useAppStateSnapshot } from '@/state/app-state' export interface DefaultLayoutProps { headerTitle?: string hideMobileMenu?: boolean } /** * Base layout for all project pages in the dashboard, rendered as the first child on all page files within a project. * * A second layout as the child to this is required, and the layout depends on which section of the dashboard the page is on. (e.g Auth - AuthLayout) * * The base layout handles rendering the following UI components: * - App banner (e.g for notices or incidents) * - Mobile navigation bar * - First level side navigation bar (e.g For navigating to Table Editor, SQL Editor, Database page, etc) */ export const DefaultLayout = ({ children, headerTitle, hideMobileMenu, }: PropsWithChildren) => { const { ref } = useParams() const router = useRouter() const appSnap = useAppStateSnapshot() const [lastVisitedOrganization] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.LAST_VISITED_ORGANIZATION, '' ) const backToDashboardURL = router.pathname.startsWith('/account') ? appSnap.lastRouteBeforeVisitingAccountPage.length > 0 ? appSnap.lastRouteBeforeVisitingAccountPage : IS_PLATFORM && !!lastVisitedOrganization ? `/org/${lastVisitedOrganization}` : IS_PLATFORM ? '/organizations' : '/project/default' : undefined useCheckLatestDeploy() const isMobile = useBreakpoint('md') const contentMinSizePercentage = 50 const contentMaxSizePercentage = 70 const [isMounted, setIsMounted] = useState(false) useEffect(() => { setIsMounted(true) }, []) // This is required to prevent layout shift when rendering resizable panels (they initially render at 50%, then shift // to whatever is specified). if (!isMounted) { return null } return (
{/* Top Banner */}
{isMobile && ( )}
{/* Main Content Area */}
{/* Sidebar - Only show for project pages, not account pages */} {!router.pathname.startsWith('/account') && } {/* Main Content with Layout Sidebar */}
{children}
) } export default DefaultLayout