Sidebar
muffled-ui-registry/sidebarFreeComponent
Collapsible app navigation on ink and paper. Off-canvas mobile sheet, icon collapse, hairline borders.
Live preview
live · rendered by the registry
Rendered by muffled-ui-registry on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.muffled.studio/r/sidebar.jsonSource
1import * as React from "react"2import { mergeProps } from "@base-ui/react/merge-props"3import { useRender } from "@base-ui/react/use-render"4import { cva, type VariantProps } from "class-variance-authority"56import { useIsMobile } from "@/registry/hooks/use-mobile"7import { cn } from "@/registry/lib/surface"8import { Button } from "@/registry/ui/button"9import { Input } from "@/registry/ui/input"10import { Separator } from "@/registry/ui/separator"11import {12 Sheet,13 SheetContent,14 SheetDescription,15 SheetHeader,16 SheetTitle,17} from "@/registry/ui/sheet"18import { Skeleton } from "@/registry/ui/skeleton"19import {20 Tooltip,21 TooltipContent,22 TooltipTrigger,23} from "@/registry/ui/tooltip"24import { PanelLeftIcon } from "lucide-react"2526const SIDEBAR_COOKIE_NAME = "sidebar_state"27const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 728const SIDEBAR_WIDTH = "16rem"29const SIDEBAR_WIDTH_MOBILE = "18rem"30const SIDEBAR_WIDTH_ICON = "3rem"31const SIDEBAR_KEYBOARD_SHORTCUT = "b"3233type SidebarContextProps = {34 state: "expanded" | "collapsed"35 open: boolean36 setOpen: (open: boolean) => void37 openMobile: boolean38 setOpenMobile: (open: boolean) => void39 isMobile: boolean40 toggleSidebar: () => void41}4243const SidebarContext = React.createContext<SidebarContextProps | null>(null)4445function useSidebar() {46 const context = React.useContext(SidebarContext)47 if (!context) {48 throw new Error("useSidebar must be used within a SidebarProvider.")49 }5051 return context52}5354function SidebarProvider({55 defaultOpen = true,56 open: openProp,57 onOpenChange: setOpenProp,58 className,59 style,60 children,61 ...props62}: React.ComponentProps<"div"> & {63 defaultOpen?: boolean64 open?: boolean65 onOpenChange?: (open: boolean) => void66}) {67 const isMobile = useIsMobile()68 const [openMobile, setOpenMobile] = React.useState(false)6970 // This is the internal state of the sidebar.71 // We use openProp and setOpenProp for control from outside the component.72 const [_open, _setOpen] = React.useState(defaultOpen)73 const open = openProp ?? _open74 const setOpen = React.useCallback(75 (value: boolean | ((value: boolean) => boolean)) => {76 const openState = typeof value === "function" ? value(open) : value77 if (setOpenProp) {78 setOpenProp(openState)79 } else {80 _setOpen(openState)81 }8283 // This sets the cookie to keep the sidebar state.84 document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`85 },86// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from muffled-ui-registry
All 55 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | muffled-ui-registry | Components | Free | 2 deps | |
| Alertalert | muffled-ui-registry | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | muffled-ui-registry | Components | Free | 1 dep | |
| Avataravatar | muffled-ui-registry | Components | Free | 1 dep | |
| Badgebadge | muffled-ui-registry | Components | Free | 2 deps | |
| Breadcrumbbreadcrumb | muffled-ui-registry | Components | Free | 2 deps | |
| Buttonbutton | muffled-ui-registry | Components | Free | 2 deps | |
| Button Groupbutton-group | muffled-ui-registry | Components | Free | 2 deps |
