Components

Sidebar

A composable, themeable, and customizable sidebar.

Installation

Cortexcn
pnpm dlx shadcn@latest add @cortexcn/sidebar

The sidebar reads its colors from the --sidebar tokens that shadcn init adds to your theme.

Usage

import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar } from "@/components/sidebar";

Wrap your layout in SidebarProvider, put a Sidebar next to a SidebarInset, and add a SidebarTrigger to toggle it. Press Ctrl+B (Cmd+B on a Mac) to toggle it from the keyboard.

Examples

Default

"use client"import * as React from "react"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from "@/components/dropdown-menu"import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from "@/components/item"import { Label } from "@/components/label"import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarRail, SidebarTrigger } from "@/components/sidebar"import { CheckIcon, ChevronsUpDownIcon, SearchIcon } from "lucide-react"export function SidebarDefaultExample() {  const data = {    versions: ["1.0.1", "1.1.0-alpha", "2.0.0-beta1"],    navMain: [      {        title: "Getting Started",        url: "#",        items: [          {            title: "Installation",            url: "#",          },          {            title: "Project Structure",            url: "#",          },        ],      },      {        title: "Build Your Application",        url: "#",        items: [          {            title: "Routing",            url: "#",          },          {            title: "Data Fetching",            url: "#",            isActive: true,          },          {            title: "Rendering",            url: "#",          },          {            title: "Caching",            url: "#",          },          {            title: "Styling",            url: "#",          },          {            title: "Optimizing",            url: "#",          },          {            title: "Configuring",            url: "#",          },          {            title: "Testing",            url: "#",          },          {            title: "Authentication",            url: "#",          },          {            title: "Deploying",            url: "#",          },          {            title: "Upgrading",            url: "#",          },          {            title: "Examples",            url: "#",          },        ],      },      {        title: "API Reference",        url: "#",        items: [          {            title: "Components",            url: "#",          },          {            title: "File Conventions",            url: "#",          },          {            title: "Functions",            url: "#",          },          {            title: "next.config.js Options",            url: "#",          },          {            title: "CLI",            url: "#",          },          {            title: "Edge Runtime",            url: "#",          },        ],      },      {        title: "Architecture",        url: "#",        items: [          {            title: "Accessibility",            url: "#",          },          {            title: "Fast Refresh",            url: "#",          },          {            title: "Next.js Compiler",            url: "#",          },          {            title: "Supported Browsers",            url: "#",          },          {            title: "Turbopack",            url: "#",          },        ],      },    ],  }  const [selectedVersion, setSelectedVersion] = React.useState(data.versions[0])  return (    <SidebarProvider>      <Sidebar>        <SidebarHeader>          <SidebarMenu>            <SidebarMenuItem>              <DropdownMenu>                <DropdownMenuTrigger asChild>                  <SidebarMenuButton                    size="lg"                    className="data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground"                  >                    <Item className="p-0" size="xs">                      <ItemContent>                        <ItemTitle className="text-sm">Documentation</ItemTitle>                        <ItemDescription>v{selectedVersion}</ItemDescription>                      </ItemContent>                      <ItemActions>                        <ChevronsUpDownIcon />                      </ItemActions>                    </Item>                  </SidebarMenuButton>                </DropdownMenuTrigger>                <DropdownMenuContent>                  <DropdownMenuGroup>                    {data.versions.map((version) => (                      <DropdownMenuItem                        key={version}                        onSelect={() => setSelectedVersion(version)}                      >                        v{version}{" "}                        {version === selectedVersion && (                          <CheckIcon className="ml-auto" />                        )}                      </DropdownMenuItem>                    ))}                  </DropdownMenuGroup>                </DropdownMenuContent>              </DropdownMenu>            </SidebarMenuItem>          </SidebarMenu>          <form>            <SidebarGroup className="py-0">              <SidebarGroupContent className="relative">                <Label htmlFor="search" className="sr-only">                  Search                </Label>                <SidebarInput                  id="search"                  placeholder="Search the docs..."                  className="pl-8"                />                <SearchIcon className="pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 opacity-50 select-none" />              </SidebarGroupContent>            </SidebarGroup>          </form>        </SidebarHeader>        <SidebarContent>          {data.navMain.map((item) => (            <SidebarGroup key={item.title}>              <SidebarGroupLabel>{item.title}</SidebarGroupLabel>              <SidebarGroupContent>                <SidebarMenu>                  {item.items.map((subItem) => (                    <SidebarMenuItem key={subItem.title}>                      <SidebarMenuButton asChild isActive={subItem.isActive}>                        <a href={subItem.url}>{subItem.title}</a>                      </SidebarMenuButton>                    </SidebarMenuItem>                  ))}                </SidebarMenu>              </SidebarGroupContent>            </SidebarGroup>          ))}        </SidebarContent>        <SidebarRail />      </Sidebar>      <SidebarInset>        <header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">          <SidebarTrigger className="-ml-1" />        </header>        <div className="flex flex-1 flex-col gap-4 p-4">          <div className="grid auto-rows-min gap-4 md:grid-cols-3">            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />          </div>          <div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />        </div>      </SidebarInset>    </SidebarProvider>  )}

Floating

"use client"import { Button } from "@/components/button"import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/card"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from "@/components/dropdown-menu"import { Field } from "@/components/field"import { Item, ItemContent, ItemDescription, ItemTitle } from "@/components/item"import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarRail, SidebarTrigger } from "@/components/sidebar"import { MoreHorizontalIcon } from "lucide-react"export function SidebarFloatingExample() {  const data = {    navMain: [      {        title: "Getting Started",        url: "#",        items: [          {            title: "Installation",            url: "#",          },          {            title: "Project Structure",            url: "#",          },        ],      },      {        title: "Build Your Application",        url: "#",        items: [          {            title: "Routing",            url: "#",          },          {            title: "Data Fetching",            url: "#",            isActive: true,          },          {            title: "Rendering",            url: "#",          },          {            title: "Caching",            url: "#",          },          {            title: "Styling",            url: "#",          },          {            title: "Optimizing",            url: "#",          },          {            title: "Configuring",            url: "#",          },          {            title: "Testing",            url: "#",          },          {            title: "Authentication",            url: "#",          },          {            title: "Deploying",            url: "#",          },          {            title: "Upgrading",            url: "#",          },          {            title: "Examples",            url: "#",          },        ],      },      {        title: "API Reference",        url: "#",        items: [          {            title: "Components",            url: "#",          },          {            title: "File Conventions",            url: "#",          },          {            title: "Functions",            url: "#",          },          {            title: "next.config.js Options",            url: "#",          },          {            title: "CLI",            url: "#",          },          {            title: "Edge Runtime",            url: "#",          },        ],      },      {        title: "Architecture",        url: "#",        items: [          {            title: "Accessibility",            url: "#",          },          {            title: "Fast Refresh",            url: "#",          },          {            title: "Next.js Compiler",            url: "#",          },          {            title: "Supported Browsers",            url: "#",          },          {            title: "Turbopack",            url: "#",          },        ],      },    ],  }  return (    <SidebarProvider className="bg-background">      <Sidebar variant="floating">        <SidebarHeader>          <SidebarMenu>            <SidebarMenuItem>              <SidebarMenuButton size="lg" asChild>                <a href="#">                  <Item className="p-0" size="xs">                    <ItemContent>                      <ItemTitle className="text-sm">Documentation</ItemTitle>                      <ItemDescription>v1.0.0</ItemDescription>                    </ItemContent>                  </Item>                </a>              </SidebarMenuButton>            </SidebarMenuItem>          </SidebarMenu>        </SidebarHeader>        <SidebarContent>          <SidebarGroup>            <SidebarMenu>              {data.navMain.map((item) => (                <DropdownMenu key={item.title}>                  <SidebarMenuItem>                    <DropdownMenuTrigger asChild>                      <SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">                        {item.title}{" "}                        <MoreHorizontalIcon className="ml-auto" />                      </SidebarMenuButton>                    </DropdownMenuTrigger>                    {item.items?.length ? (                      <DropdownMenuContent side="right" align="start">                        <DropdownMenuGroup>                          {item.items.map((subItem) => (                            <DropdownMenuItem asChild key={subItem.title}>                              <a href={subItem.url}>{subItem.title}</a>                            </DropdownMenuItem>                          ))}                        </DropdownMenuGroup>                      </DropdownMenuContent>                    ) : null}                  </SidebarMenuItem>                </DropdownMenu>              ))}            </SidebarMenu>          </SidebarGroup>        </SidebarContent>        <SidebarFooter>          <SidebarGroup className="pb-1">            <Card size="sm" className="-mx-1">              <CardHeader>                <CardTitle className="text-sm">                  Subscribe to our newsletter                </CardTitle>                <CardDescription>                  Opt-in to receive updates and news about the sidebar.                </CardDescription>              </CardHeader>              <CardContent>                <form>                  <Field>                    <SidebarInput type="email" placeholder="Email" />                    <Button                      className="w-full bg-sidebar-primary text-sidebar-primary-foreground"                      size="sm"                    >                      Subscribe                    </Button>                  </Field>                </form>              </CardContent>            </Card>          </SidebarGroup>        </SidebarFooter>        <SidebarRail />      </Sidebar>      <SidebarInset>        <header className="flex h-16 shrink-0 items-center gap-2 px-4">          <SidebarTrigger className="-ml-1" />        </header>        <div className="flex flex-1 flex-col gap-4 p-4 pt-0">          <div className="grid auto-rows-min gap-4 md:grid-cols-3">            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />          </div>          <div className="min-h-screen flex-1 rounded-xl bg-muted/50 md:min-h-min" />        </div>      </SidebarInset>    </SidebarProvider>  )}

Collapsible to icons

"use client"import * as React from "react"import { Avatar, AvatarFallback, AvatarImage } from "@/components/avatar"import { Button } from "@/components/button"import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/collapsible"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/dropdown-menu"import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "@/components/item"import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarTrigger } from "@/components/sidebar"import { BookOpen, BotIcon, ChevronRightIcon, ChevronsUpDownIcon, FrameIcon, MapIcon, PieChartIcon, Settings2Icon, TerminalSquareIcon } from "lucide-react"export function SidebarIconExample() {  const data = {    user: {      name: "shadcn",      email: "m@example.com",      avatar: "/avatars/shadcn.jpg",    },    teams: [      {        name: "Acme Inc",        plan: "Enterprise",      },      {        name: "Acme Corp.",        plan: "Startup",      },      {        name: "Evil Corp.",        plan: "Free",      },    ],    navMain: [      {        title: "Playground",        url: "#",        icon: (          <TerminalSquareIcon />        ),        isActive: true,        items: [          {            title: "History",            url: "#",          },          {            title: "Starred",            url: "#",          },          {            title: "Settings",            url: "#",          },        ],      },      {        title: "Models",        url: "#",        icon: (          <BotIcon />        ),        items: [          {            title: "Genesis",            url: "#",          },          {            title: "Explorer",            url: "#",          },          {            title: "Quantum",            url: "#",          },        ],      },      {        title: "Documentation",        url: "#",        icon: (          <BookOpen />        ),        items: [          {            title: "Introduction",            url: "#",          },          {            title: "Get Started",            url: "#",          },          {            title: "Tutorials",            url: "#",          },          {            title: "Changelog",            url: "#",          },        ],      },      {        title: "Settings",        url: "#",        icon: (          <Settings2Icon />        ),        items: [          {            title: "General",            url: "#",          },          {            title: "Team",            url: "#",          },          {            title: "Billing",            url: "#",          },          {            title: "Limits",            url: "#",          },        ],      },    ],    projects: [      {        name: "Design Engineering",        url: "#",        icon: (          <FrameIcon />        ),      },      {        name: "Sales & Marketing",        url: "#",        icon: (          <PieChartIcon />        ),      },      {        name: "Travel",        url: "#",        icon: (          <MapIcon />        ),      },    ],  }  const [activeTeam, setActiveTeam] = React.useState(data.teams[0])  return (    <SidebarProvider>      <Sidebar collapsible="icon">        <SidebarHeader>          <SidebarMenu>            <SidebarMenuItem>              <DropdownMenu>                <DropdownMenuTrigger asChild>                  <SidebarMenuButton                    size="lg"                    className="data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground"                  >                    <Button size="icon-sm" asChild className="size-8">                      <span>                        <svg                          xmlns="http://www.w3.org/2000/svg"                          viewBox="0 0 256 256"                        >                          <rect width="256" height="256" fill="none"></rect>                          <line                            x1="208"                            y1="128"                            x2="128"                            y2="208"                            fill="none"                            stroke="currentColor"                            strokeLinecap="round"                            strokeLinejoin="round"                            strokeWidth="32"                          ></line>                          <line                            x1="192"                            y1="40"                            x2="40"                            y2="192"                            fill="none"                            stroke="currentColor"                            strokeLinecap="round"                            strokeLinejoin="round"                            strokeWidth="32"                          ></line>                        </svg>                      </span>                    </Button>                    <div className="grid flex-1 text-left text-sm leading-tight">                      <span className="truncate font-medium">                        {activeTeam.name}                      </span>                      <span className="truncate text-xs">                        {activeTeam.plan}                      </span>                    </div>                    <ChevronsUpDownIcon />                  </SidebarMenuButton>                </DropdownMenuTrigger>                <DropdownMenuContent>                  <DropdownMenuGroup>                    <DropdownMenuLabel>Teams</DropdownMenuLabel>                    {data.teams.map((team) => (                      <DropdownMenuItem                        key={team.name}                        onClick={() => setActiveTeam(team)}                      >                        {team.name}                      </DropdownMenuItem>                    ))}                  </DropdownMenuGroup>                </DropdownMenuContent>              </DropdownMenu>            </SidebarMenuItem>          </SidebarMenu>        </SidebarHeader>        <SidebarContent>          <SidebarGroup>            <SidebarGroupLabel>Platform</SidebarGroupLabel>            <SidebarMenu>              {data.navMain.map((item) => (                <Collapsible                  key={item.title}                  asChild                  defaultOpen={item.isActive}                  className="group/collapsible"                >                  <SidebarMenuItem>                    <SidebarMenuButton tooltip={item.title} asChild>                      <CollapsibleTrigger>                        {item.icon}                        <span>{item.title}</span>                        <ChevronRightIcon className="ml-auto transition-transform duration-100 group-data-open/collapsible:rotate-90" />                      </CollapsibleTrigger>                    </SidebarMenuButton>                    <CollapsibleContent>                      <SidebarMenuSub>                        {item.items?.map((subItem) => (                          <SidebarMenuSubItem key={subItem.title}>                            <SidebarMenuSubButton asChild>                              <a href={subItem.url}>{subItem.title}</a>                            </SidebarMenuSubButton>                          </SidebarMenuSubItem>                        ))}                      </SidebarMenuSub>                    </CollapsibleContent>                  </SidebarMenuItem>                </Collapsible>              ))}            </SidebarMenu>          </SidebarGroup>          <SidebarGroup className="group-data-[collapsible=icon]:hidden">            <SidebarGroupLabel>Projects</SidebarGroupLabel>            <SidebarMenu>              {data.projects.map((item) => (                <SidebarMenuItem key={item.name}>                  <SidebarMenuButton asChild>                    <a href={item.url}>                      {item.icon}                      {item.name}                    </a>                  </SidebarMenuButton>                </SidebarMenuItem>              ))}            </SidebarMenu>          </SidebarGroup>        </SidebarContent>        <SidebarFooter>          <SidebarMenu>            <SidebarMenuItem>              <DropdownMenu>                <DropdownMenuTrigger asChild>                  <SidebarMenuButton                    size="lg"                    className="data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground"                  >                    <Avatar>                      <AvatarImage                        src={data.user.avatar}                        alt={data.user.name}                      />                      <AvatarFallback className="rounded-lg">CN</AvatarFallback>                    </Avatar>                    <div className="grid flex-1 text-left text-sm leading-tight">                      <span className="truncate font-medium">                        {data.user.name}                      </span>                      <span className="truncate text-xs">                        {data.user.email}                      </span>                    </div>                    <ChevronsUpDownIcon />                  </SidebarMenuButton>                </DropdownMenuTrigger>                <DropdownMenuContent>                  <DropdownMenuGroup>                    <DropdownMenuLabel>                      <Item size="xs">                        <ItemMedia>                          <Avatar>                            <AvatarImage                              src={data.user.avatar}                              alt={data.user.name}                            />                            <AvatarFallback>CN</AvatarFallback>                          </Avatar>                        </ItemMedia>                        <ItemContent>                          <ItemTitle>{data.user.name}</ItemTitle>                          <ItemDescription> {data.user.email}</ItemDescription>                        </ItemContent>                      </Item>                    </DropdownMenuLabel>                  </DropdownMenuGroup>                  <DropdownMenuSeparator />                  <DropdownMenuGroup>                    <DropdownMenuItem>Account</DropdownMenuItem>                    <DropdownMenuItem>Billing</DropdownMenuItem>                    <DropdownMenuItem>Settings</DropdownMenuItem>                  </DropdownMenuGroup>                  <DropdownMenuSeparator />                  <DropdownMenuGroup>                    <DropdownMenuItem>Log out</DropdownMenuItem>                  </DropdownMenuGroup>                </DropdownMenuContent>              </DropdownMenu>            </SidebarMenuItem>          </SidebarMenu>        </SidebarFooter>        <SidebarRail />      </Sidebar>      <SidebarInset>        <header className="flex h-16 shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">          <div className="flex items-center gap-2 px-4">            <SidebarTrigger className="-ml-1" />          </div>        </header>        <div className="flex flex-1 flex-col gap-4 p-4">          <div className="grid auto-rows-min gap-4 md:grid-cols-3">            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />          </div>          <div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />        </div>      </SidebarInset>    </SidebarProvider>  )}

Inset

"use client"import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/collapsible"import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarTrigger } from "@/components/sidebar"import { ChartLineIcon, ChevronRightIcon, FileIcon, HomeIcon, LifeBuoy, Send, Settings2Icon, ShoppingBagIcon, ShoppingCartIcon, UserIcon } from "lucide-react"export function SidebarInsetExample() {  const data = {    navMain: [      {        title: "Dashboard",        url: "#",        icon: (          <HomeIcon />        ),        isActive: true,        items: [          {            title: "Overview",            url: "#",          },          {            title: "Analytics",            url: "#",          },        ],      },      {        title: "Analytics",        url: "#",        icon: (          <ChartLineIcon />        ),        items: [          {            title: "Reports",            url: "#",          },          {            title: "Metrics",            url: "#",          },        ],      },      {        title: "Orders",        url: "#",        icon: (          <ShoppingBagIcon />        ),        items: [          {            title: "All Orders",            url: "#",          },          {            title: "Pending",            url: "#",          },          {            title: "Completed",            url: "#",          },        ],      },      {        title: "Products",        url: "#",        icon: (          <ShoppingCartIcon />        ),        items: [          {            title: "All Products",            url: "#",          },          {            title: "Categories",            url: "#",          },        ],      },      {        title: "Invoices",        url: "#",        icon: (          <FileIcon />        ),      },      {        title: "Customers",        url: "#",        icon: (          <UserIcon />        ),      },      {        title: "Settings",        url: "#",        icon: (          <Settings2Icon />        ),      },    ],    navSecondary: [      {        title: "Support",        url: "#",        icon: (          <LifeBuoy />        ),      },      {        title: "Feedback",        url: "#",        icon: (          <Send />        ),      },    ],  }  return (    <SidebarProvider>      <Sidebar variant="inset">        <SidebarContent>          <SidebarGroup>            <SidebarGroupLabel>Dashboard</SidebarGroupLabel>            <SidebarMenu>              {data.navMain.map((item) => (                <Collapsible                  key={item.title}                  asChild                  defaultOpen={item.isActive}                >                  <SidebarMenuItem>                    <SidebarMenuButton                      asChild                      tooltip={item.title}                      isActive={item.isActive}                    >                      <a href={item.url}>                        {item.icon}                        <span>{item.title}</span>                      </a>                    </SidebarMenuButton>                    {item.items?.length ? (                      <>                        <CollapsibleTrigger asChild>                          <SidebarMenuAction className="data-[state=open]:rotate-90">                            <ChevronRightIcon />                            <span className="sr-only">Toggle</span>                          </SidebarMenuAction>                        </CollapsibleTrigger>                        <CollapsibleContent>                          <SidebarMenuSub>                            {item.items.map((subItem) => (                              <SidebarMenuSubItem key={subItem.title}>                                <SidebarMenuSubButton asChild>                                  <a href={subItem.url}>                                    <span>{subItem.title}</span>                                  </a>                                </SidebarMenuSubButton>                              </SidebarMenuSubItem>                            ))}                          </SidebarMenuSub>                        </CollapsibleContent>                      </>                    ) : null}                  </SidebarMenuItem>                </Collapsible>              ))}            </SidebarMenu>          </SidebarGroup>          <SidebarGroup className="mt-auto">            <SidebarGroupContent>              <SidebarMenu>                {data.navSecondary.map((item) => (                  <SidebarMenuItem key={item.title}>                    <SidebarMenuButton asChild size="sm">                      <a href={item.url}>                        {item.icon}                        <span>{item.title}</span>                      </a>                    </SidebarMenuButton>                  </SidebarMenuItem>                ))}              </SidebarMenu>            </SidebarGroupContent>          </SidebarGroup>        </SidebarContent>        <SidebarRail />      </Sidebar>      <SidebarInset>        <header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">          <SidebarTrigger className="-ml-1" />        </header>        <div className="flex flex-1 flex-col gap-4 p-4">          <div className="grid auto-rows-min gap-4 md:grid-cols-3">            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />            <div className="aspect-video rounded-xl bg-muted/50" />          </div>          <div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />        </div>      </SidebarInset>    </SidebarProvider>  )}

Adapted from the shadcn/ui Sidebar (MIT).