import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" 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" type SidebarContextType = { state: "expanded" | "collapsed" open: boolean setOpen: (open: boolean) => void openMobile: boolean setOpenMobile: (open: boolean) => void isMobile: boolean toggleSidebar: () => void } const SidebarContext = React.createContext(undefined) function useSidebar() { const context = React.useContext(SidebarContext) if (!context) { throw new Error("useSidebar must be used within a SidebarProvider.") } return context } const SidebarProvider = React.forwardRef< HTMLDivElement, React.HTMLAttributes & { defaultOpen?: boolean open?: boolean onOpenChange?: (open: boolean) => void } >( ( { defaultOpen = true, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }, ref ) => { const isMobile = useIsMobile() const [openMobile, setOpenMobile] = React.useState(false) const [_open, _setOpen] = React.useState(defaultOpen) const open = openProp ?? _open const setOpen = React.useCallback( (open: boolean) => { setOpenProp?.(open) _setOpen(open) document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` }, [setOpenProp] ) const state = open ? "expanded" : "collapsed" const toggleSidebar = React.useCallback(() => { return isMobile ? setOpenMobile(!openMobile) : setOpen(!open) }, [isMobile, open, setOpen, openMobile]) React.useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) { event.preventDefault() toggleSidebar() } } window.addEventListener("keydown", handleKeyDown) return () => window.removeEventListener("keydown", handleKeyDown) }, [toggleSidebar]) return (
{children}
) } ) SidebarProvider.displayName = "SidebarProvider" const Sidebar = React.forwardRef< HTMLDivElement, React.HTMLAttributes & { side?: "left" | "right" variant?: "sidebar" | "floating" | "inset" collapsible?: "offcanvas" | "icon" | "none" } >( ( { side = "left", variant = "sidebar", collapsible = "offcanvas", className, ...props }, ref ) => { const { isMobile, state, openMobile, setOpenMobile } = useSidebar() if (collapsible === "none") { return (
) } if (isMobile) { return (
) } return (