import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva } from "class-variance-authority"; import { Menu } from "lucide-react"; import { useIsMobile } from "@/hooks/use-mobile"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { Skeleton } from "@/components/ui/skeleton"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; const SIDEBAR_COOKIE_NAME = "sidebar_state"; const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; const SIDEBAR_WIDTH = "16rem"; const SIDEBAR_WIDTH_MOBILE = "18rem"; const SIDEBAR_WIDTH_ICON = "3rem"; const SIDEBAR_KEYBOARD_SHORTCUT = "b"; const SidebarContext = React.createContext(null); function useSidebar() { const context = React.useContext(SidebarContext); if (!context) { throw new Error("useSidebar must be used within a SidebarProvider."); } return context; } function readSidebarCookie() { if (typeof document === "undefined") return undefined; // SSR safety const m = document.cookie.match(new RegExp(`(?:^|; )${SIDEBAR_COOKIE_NAME}=([^;]*)`)); return m ? m[1] === "true" : undefined; } const SidebarProvider = React.forwardRef(({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }, ref) => { const isMobile = useIsMobile(); const [openMobile, setOpenMobile] = React.useState(false); const cookieOpen = readSidebarCookie(); const [_open, _setOpen] = React.useState(cookieOpen !== undefined ? cookieOpen : defaultOpen); const open = openProp ?? _open; const setOpen = React.useCallback((value) => { const openState = typeof value === "function" ? value(open) : value; if (setOpenProp) { setOpenProp(openState); } else { _setOpen(openState); } document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`; }, [setOpenProp, open]); const toggleSidebar = React.useCallback(() => { return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open); }, [isMobile, setOpen, setOpenMobile]); const state = open ? "expanded" : "collapsed"; const contextValue = React.useMemo(() => ({ state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar, }), [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]); return ( {/* FIX: remove flex + w-full wrapper */}
{children}
); }); SidebarProvider.displayName = "SidebarProvider"; const Sidebar = React.forwardRef(({ side = "left", variant = "sidebar", collapsible = "offcanvas", className, children, ...props }, ref) => { const { isMobile, state, openMobile, setOpenMobile } = useSidebar(); if (collapsible === "none") { return (
{children}
); } if (isMobile) { return ( Sidebar Displays the mobile sidebar.
{children}
); } return (
{/* This is what handles the sidebar gap on desktop */}
); }); Sidebar.displayName = "Sidebar"; const SidebarTrigger = React.forwardRef(({ className, onClick, ...props }, ref) => { const { toggleSidebar } = useSidebar(); return (); }); SidebarTrigger.displayName = "SidebarTrigger"; const SidebarRail = React.forwardRef(({ className, ...props }, ref) => { const { toggleSidebar } = useSidebar(); return (