"use client"; import { useEffect, useState } from "react"; import { SidebarNav } from "./SidebarNav"; import { WatchlistSidebar } from "./WatchlistSidebar"; import { SymbolHeader } from "./SymbolHeader"; import { MobileTabNav } from "./MobileTabNav"; import { CommandPalette } from "./CommandPalette"; import { CollapsibleProvider, useCollapsibleContext } from "@/lib/collapsible-context"; import { useKeyboardShortcuts } from "@/lib/useKeyboardShortcuts"; const MOBILE_BREAKPOINT = 768; const TABLET_BREAKPOINT = 1024; function useViewport() { const [width, setWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 1200); useEffect(() => { const handler = () => setWidth(window.innerWidth); window.addEventListener("resize", handler); return () => window.removeEventListener("resize", handler); }, []); return width; } /** * Inner component that attaches the global Escape listener. * Wrapped in CollapsibleProvider so all CollapsibleSections can register. */ function LayoutShellInner({ children }: { children: React.ReactNode }) { const { openSectionId, setOpenSectionId } = useCollapsibleContext(); const viewportWidth = useViewport(); const isMobile = viewportWidth < MOBILE_BREAKPOINT; const isTablet = viewportWidth >= MOBILE_BREAKPOINT && viewportWidth < TABLET_BREAKPOINT; // Keyboard shortcuts: Escape closes open sections, modals useKeyboardShortcuts([ { key: "Escape", handler: () => { if (openSectionId) { setOpenSectionId(null); } }, }, ]); // Global Escape listener: collapse the currently open section. useEffect(() => { const handler = (e: KeyboardEvent) => { if (e.key === "Escape" && openSectionId) { e.preventDefault(); // Collapse the currently open section by clearing the shared state. // Individual CollapsibleSection Escape handlers also respond to this. setOpenSectionId(null); } }; window.addEventListener("keydown", handler, true); // capture phase return () => window.removeEventListener("keydown", handler, true); }, [openSectionId, setOpenSectionId]); return (
{/* Symbol Header — always visible */} {/* Global command palette (⌘K) */} {/* Main Content Area — responsive layout */} {isMobile ? ( /* Mobile: single column, no sidebar */ <>
{children}
) : isTablet ? ( /* Tablet: 2-column layout, watchlist accessible via compact bar */
{/* Compact horizontal watchlist bar */}
{/* Center content */}
{children}
{/* Right analytics — drops below on tablet */}
) : ( /* Desktop: 3-column layout */
{/* Left Sidebar Navigation */} {/* Watchlist Sidebar */} {/* Content */}
{children}
)}
); } /** * Main layout shell for the redesigned terminal. * - Desktop (>1024px): Sidebar + Watchlist + Header + Content (3-column) * - Tablet (768-1024px): Watchlist + Header + Content (2-column, sidebar hidden) * - Mobile (<768px): Header + Content (single column) + MobileTabNav */ export function LayoutShell({ children }: { children: React.ReactNode }) { return ( {children} ); }