({
defaultOpen = true,
open: openProp,
onOpenChange: setOpenProp,
className,
style,
children,
...props
}: React.ComponentProps<"div"> & {
defaultOpen?: boolean
open?: boolean
onOpenChange?: (open: boolean) => void
})
| 54 | } |
| 55 | |
| 56 | function SidebarProvider({ |
| 57 | defaultOpen = true, |
| 58 | open: openProp, |
| 59 | onOpenChange: setOpenProp, |
| 60 | className, |
| 61 | style, |
| 62 | children, |
| 63 | ...props |
| 64 | }: React.ComponentProps<"div"> & { |
| 65 | defaultOpen?: boolean |
| 66 | open?: boolean |
| 67 | onOpenChange?: (open: boolean) => void |
| 68 | }) { |
| 69 | const isMobile = useIsMobile() |
| 70 | const [openMobile, setOpenMobile] = React.useState(false) |
| 71 | |
| 72 | // This is the internal state of the sidebar. |
| 73 | // We use openProp and setOpenProp for control from outside the component. |
| 74 | const [_open, _setOpen] = React.useState(defaultOpen) |
| 75 | const open = openProp ?? _open |
| 76 | const setOpen = React.useCallback( |
| 77 | (value: boolean | ((value: boolean) => boolean)) => { |
| 78 | const openState = typeof value === "function" ? value(open) : value |
| 79 | if (setOpenProp) { |
| 80 | setOpenProp(openState) |
| 81 | } else { |
| 82 | _setOpen(openState) |
| 83 | } |
| 84 | |
| 85 | // This sets the cookie to keep the sidebar state. |
| 86 | document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` |
| 87 | }, |
| 88 | [setOpenProp, open] |
| 89 | ) |
| 90 | |
| 91 | // Helper to toggle the sidebar. |
| 92 | const toggleSidebar = React.useCallback(() => { |
| 93 | return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open) |
| 94 | }, [isMobile, setOpen, setOpenMobile]) |
| 95 | |
| 96 | // Adds a keyboard shortcut to toggle the sidebar. |
| 97 | React.useEffect(() => { |
| 98 | const handleKeyDown = (event: KeyboardEvent) => { |
| 99 | if ( |
| 100 | event.key === SIDEBAR_KEYBOARD_SHORTCUT && |
| 101 | (event.metaKey || event.ctrlKey) |
| 102 | ) { |
| 103 | event.preventDefault() |
| 104 | toggleSidebar() |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | window.addEventListener("keydown", handleKeyDown) |
| 109 | return () => window.removeEventListener("keydown", handleKeyDown) |
| 110 | }, [toggleSidebar]) |
| 111 | |
| 112 | // We add a state so that we can do data-state="expanded" or "collapsed". |
| 113 | // This makes it easier to style the sidebar with Tailwind classes. |
nothing calls this directly
no test coverage detected