JavaScript 56.7%
TypeScript 42.6%
1"use client";23import { useEffect } from "react";4import { motion } from "framer-motion";5import Sidebar from "./Sidebar";6import MobileNav from "./MobileNav";7import MobileTabBar from "./MobileTabBar";8import TopBar from "./TopBar";9import CommandPalette from "./CommandPalette";10import PreferencesModal from "../theme/PreferencesModal";11import AiPanel from "../ai/AiPanel";12import TopLoader from "../ui/TopLoader";13import { ShellProvider, useShell } from "./ShellContext";1415interface AppShellProps {16 children: React.ReactNode;17 /** Masquer la barre supérieure (pages qui gèrent leur propre en-tête plein écran) */18 hideTopBar?: boolean;19}2021function ShellFrame({ children, hideTopBar }: AppShellProps) {22 const { sidebarCollapsed, toggleSidebar, mobileNavOpen, setMobileNavOpen } = useShell();2324 // ⌘B / Ctrl+B : replier la barre latérale25 useEffect(() => {26 const onKey = (e: KeyboardEvent) => {27 if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "b") {28 const t = e.target as HTMLElement | null;29 if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;30 e.preventDefault();31 toggleSidebar();32 }33 };34 window.addEventListener("keydown", onKey);35 return () => window.removeEventListener("keydown", onKey);36 }, [toggleSidebar]);3738 return (39 <div className="h-[100dvh] overflow-hidden bg-canvas flex transition-colors">40 <TopLoader />4142 {/* Barre latérale desktop (repliable) */}43 <motion.div44 initial={false}45 animate={{ width: sidebarCollapsed ? 72 : 264 }}46 transition={{ type: "spring", stiffness: 380, damping: 36 }}47 className="hidden lg:flex flex-col shrink-0 h-full overflow-hidden"48 >49 <Sidebar collapsed={sidebarCollapsed} showCollapse />50 </motion.div>5152 {/* Tiroir mobile */}53 <MobileNav isOpen={mobileNavOpen} onClose={() => setMobileNavOpen(false)} />5455 {/* Colonne principale */}56 <div className="flex-1 flex flex-col min-w-0 h-full overflow-hidden">57 {!hideTopBar && <TopBar />}58 <main className="flex-1 overflow-auto min-h-0 pb-tabbar" id="main">59 {children}60 </main>61 </div>6263 <MobileTabBar />64 <CommandPalette />65 <PreferencesModal />66 <AiPanel />67 </div>68 );69}7071export default function AppShell(props: AppShellProps) {72 return (73 <ShellProvider>74 <ShellFrame {...props} />75 </ShellProvider>76 );77}78