From 6cb2a1fd6512577ad433e75df508b3dc1161fe65 Mon Sep 17 00:00:00 2001 From: shadcn Date: Thu, 22 Jan 2026 23:55:06 +0400 Subject: [PATCH] fix: sidebar --- apps/v4/examples/base/ui/sidebar.tsx | 16 ++++++++-------- apps/v4/examples/radix/ui/sidebar.tsx | 16 ++++++++-------- apps/v4/public/r/styles/base-lyra/sidebar.json | 2 +- apps/v4/public/r/styles/base-maia/sidebar.json | 2 +- apps/v4/public/r/styles/base-mira/sidebar.json | 2 +- apps/v4/public/r/styles/base-nova/sidebar.json | 2 +- apps/v4/public/r/styles/base-vega/sidebar.json | 2 +- apps/v4/public/r/styles/radix-lyra/sidebar.json | 2 +- apps/v4/public/r/styles/radix-maia/sidebar.json | 2 +- apps/v4/public/r/styles/radix-mira/sidebar.json | 2 +- apps/v4/public/r/styles/radix-nova/sidebar.json | 2 +- apps/v4/public/r/styles/radix-vega/sidebar.json | 2 +- apps/v4/registry/bases/base/ui/sidebar.tsx | 16 ++++++++-------- apps/v4/registry/bases/radix/ui/sidebar.tsx | 16 ++++++++-------- 14 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/v4/examples/base/ui/sidebar.tsx b/apps/v4/examples/base/ui/sidebar.tsx index 65972c35e1..f7af8af2c7 100644 --- a/apps/v4/examples/base/ui/sidebar.tsx +++ b/apps/v4/examples/base/ui/sidebar.tsx @@ -152,14 +152,14 @@ function SidebarProvider({ function Sidebar({ side = "left", variant = "sidebar", - collapsible = "offExamples", + collapsible = "offcanvas", className, children, ...props }: React.ComponentProps<"div"> & { side?: "left" | "right" variant?: "sidebar" | "floating" | "inset" - collapsible?: "offExamples" | "icon" | "none" + collapsible?: "offcanvas" | "icon" | "none" }) { const { isMobile, state, openMobile, setOpenMobile } = useSidebar() @@ -217,7 +217,7 @@ function Sidebar({ data-slot="sidebar-gap" className={cn( "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", - "group-data-[collapsible=offExamples]:w-0", + "group-data-[collapsible=offcanvas]:w-0", "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" @@ -229,8 +229,8 @@ function Sidebar({ className={cn( "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex", side === "left" - ? "left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]" - : "right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]", + ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" + : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", // Adjust the padding for floating and inset variants. variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" @@ -298,9 +298,9 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", - "hover:group-data-[collapsible=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full", - "[[data-side=left][data-collapsible=offExamples]_&]:-right-2", - "[[data-side=right][data-collapsible=offExamples]_&]:-left-2", + "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full", + "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", + "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", className )} {...props} diff --git a/apps/v4/examples/radix/ui/sidebar.tsx b/apps/v4/examples/radix/ui/sidebar.tsx index 108aa24341..fdc3143ecb 100644 --- a/apps/v4/examples/radix/ui/sidebar.tsx +++ b/apps/v4/examples/radix/ui/sidebar.tsx @@ -151,14 +151,14 @@ function SidebarProvider({ function Sidebar({ side = "left", variant = "sidebar", - collapsible = "offExamples", + collapsible = "offcanvas", className, children, ...props }: React.ComponentProps<"div"> & { side?: "left" | "right" variant?: "sidebar" | "floating" | "inset" - collapsible?: "offExamples" | "icon" | "none" + collapsible?: "offcanvas" | "icon" | "none" }) { const { isMobile, state, openMobile, setOpenMobile } = useSidebar() @@ -216,7 +216,7 @@ function Sidebar({ data-slot="sidebar-gap" className={cn( "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", - "group-data-[collapsible=offExamples]:w-0", + "group-data-[collapsible=offcanvas]:w-0", "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" @@ -228,8 +228,8 @@ function Sidebar({ className={cn( "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex", side === "left" - ? "left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]" - : "right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]", + ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" + : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", // Adjust the padding for floating and inset variants. variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" @@ -297,9 +297,9 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", - "hover:group-data-[collapsible=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full", - "[[data-side=left][data-collapsible=offExamples]_&]:-right-2", - "[[data-side=right][data-collapsible=offExamples]_&]:-left-2", + "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full", + "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", + "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", className )} {...props} diff --git a/apps/v4/public/r/styles/base-lyra/sidebar.json b/apps/v4/public/r/styles/base-lyra/sidebar.json index 28b5eba686..b318ace5f2 100644 --- a/apps/v4/public/r/styles/base-lyra/sidebar.json +++ b/apps/v4/public/r/styles/base-lyra/sidebar.json @@ -12,7 +12,7 @@ "files": [ { "path": "registry/base-lyra/ui/sidebar.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { Button } from \"@/registry/base-lyra/ui/button\"\nimport { Input } from \"@/registry/base-lyra/ui/input\"\nimport { Separator } from \"@/registry/base-lyra/ui/separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"@/registry/base-lyra/ui/sheet\"\nimport { Skeleton } from \"@/registry/base-lyra/ui/skeleton\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/registry/base-lyra/ui/tooltip\"\nimport { useIsMobile } from \"@/registry/new-york-v4/hooks/use-mobile\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\"\n open: boolean\n setOpen: (open: boolean) => void\n openMobile: boolean\n setOpenMobile: (open: boolean) => void\n isMobile: boolean\n toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext(null)\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext)\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\")\n }\n\n return context\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}) {\n const isMobile = useIsMobile()\n const [openMobile, setOpenMobile] = React.useState(false)\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen)\n const open = openProp ?? _open\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value\n if (setOpenProp) {\n setOpenProp(openState)\n } else {\n _setOpen(openState)\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n },\n [setOpenProp, open]\n )\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\n }, [isMobile, setOpen, setOpenMobile])\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault()\n toggleSidebar()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [toggleSidebar])\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\"\n\n const contextValue = React.useMemo(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\n )\n\n return (\n \n \n {children}\n \n \n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offExamples\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offExamples\" | \"icon\" | \"none\"\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n if (collapsible === \"none\") {\n return (\n \n {children}\n \n )\n }\n\n if (isMobile) {\n return (\n \n button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n side={side}\n >\n \n Sidebar\n Displays the mobile sidebar.\n \n
{children}
\n \n
\n )\n }\n\n return (\n