shadimage
lumiui
blocksidebar-02source: ok · hit

Sidebar 02

Dashboard layout with sidebar and main content area.

npx shadcn add "https://www.lumiui.dev/r/sidebar-02.json"
free

Where it goes

sidebardashboard-shellkanban

Use cases

dashboard

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light

Registry dependencies

@lumi-ui/sidebar@lumi-ui/separator@lumi-ui/scroll-area@lumi-ui/dropdown-menu@lumi-ui/chart@lumi-ui/collapsible

Files4 · source cached 10/14/2026, 3:12:55 PM

registry/blocks/sidebar-02/page.tsx
import { cookies } from "next/headers";
import type { Layout } from "react-resizable-panels";
import { AppSidebar } from "@/registry/blocks/sidebar-02/components/app-sidebar";
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/registry/ui/breadcrumb";
import { Separator } from "@/registry/ui/separator";
import {
  MainContent,
  SidebarProvider,
  SidebarTrigger,
} from "@/registry/ui/sidebar";

const GROUP_ID = "main-layout-persistence";

export default async function Page() {
  const cookieStore = await cookies();
  const layoutCookie = cookieStore.get(GROUP_ID);

  const defaultLayout: Layout = layoutCookie
    ? JSON.parse(layoutCookie.value)
    : undefined;

  return (
    <SidebarProvider
      collapsibleType="sidebar"
      defaultLayout={defaultLayout}
      groupId={GROUP_ID}
    >
      <AppSidebar />
      <MainContent className="flex flex-col">
        <header className="flex h-12 bg-background z-10 sticky top-0 items-center gap-2 p-2 sm:p-4">
          <SidebarTrigger />
          <Separator className="mr-2 h-4" orientation="vertical" />
          <Breadcrumb>
            <BreadcrumbList>
              <BreadcrumbItem className="hidden md:block">
                <BreadcrumbLink href="#">Dashboard</BreadcrumbLink>
              </BreadcrumbItem>
              <BreadcrumbSeparator className="hidden md:block" />
              <BreadcrumbItem>
                <BreadcrumbPage>Financial Performance</BreadcrumbPage>
              </BreadcrumbItem>
            </BreadcrumbList>
          </Breadcrumb>
        </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="bg-muted/50 aspect-video rounded-xl" />
            <div className="bg-muted/50 aspect-video rounded-xl" />
            <div className="bg-muted/50 aspect-video rounded-xl" />
          </div>
          <div className="bg-muted/50 min-h-[100vh] flex-1 rounded-xl md:min-h-min" />
        </div>
      </MainContent>
    </SidebarProvider>
  );
}
registry/blocks/sidebar-02/components/app-sidebar.tsx
import { ScrollArea } from "@/registry/ui/scroll-area";
import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarHeader,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
} from "@/registry/ui/sidebar";
import { NavMain } from "./nav-main";
import { VersionSwitcher } from "./version-switcher";

export function AppSidebar() {
  return (
    <Sidebar>
      <SidebarHeader>
        <VersionSwitcher
          defaultVersion={data.versions[0]}
          versions={data.versions}
        />
      </SidebarHeader>
      <SidebarContent>
        <ScrollArea gradientScrollFade>
          <NavMain items={data.navMain} />
          {data.navMain.map((item) => (
            <SidebarGroup key={item.title}>
              <SidebarGroupLabel>{item.title}</SidebarGroupLabel>
              <SidebarGroupContent>
                <SidebarMenu>
                  {item.items.map((item) => (
                    <SidebarMenuItem key={item.title}>
                      <SidebarMenuButton
                        isActive={item.isActive}
                        render={<a href={item.url}>{item.title}</a>}
                        tooltip={{
                          children: "hello",
                        }}
                      />
                    </SidebarMenuItem>
                  ))}
                </SidebarMenu>
              </SidebarGroupContent>
            </SidebarGroup>
          ))}
        </ScrollArea>
      </SidebarContent>
    </Sidebar>
  );
}

const data = {
  navMain: [
    {
      items: [
        {
          title: "Overview",
          url: "#",
        },
        {
          isActive: true,
          title: "Analytics",
          url: "#",
        },
        {
          title: "Reports",
          url: "#",
        },
      ],
      title: "Dashboard",
      url: "#",
    },
    {
      items: [
        {
          title: "All Users",
          url: "#",
        },
        {
          title: "Roles & Permissions",
          url: "#",
        },
        {
          title: "Teams",
          url: "#",
        },
        {
          title: "Invitations",
          url: "#",
        },
        {
          title: "Activity Logs",
          url: "#",
        },
      ],
      title: "User Management",
      url: "#",
    },
    {
      items: [
        {
          title: "All Projects",
          url: "#",
        },
        {
          title: "Active Projects",
          url: "#",
        },
        {
          title: "Archived",
          url: "#",
        },
        {
          title: "Templates",
          url: "#",
        },
      ],
      title: "Projects",
      url: "#",
    },
    {
      items: [
        {
          title: "Transactions",
          url: "#",
        },
        {
          title: "Subscriptions",
          url: "#",
        },
        {
          title: "Invoices",
          url: "#",
        },
        {
          title: "Billing",
          url: "#",
        },
        {
          title: "Payment Methods",
          url: "#",
        },
      ],
      title: "Sales & Revenue",
      url: "#",
    },
    {
      items: [
        {
          title: "General",
          url: "#",
        },
        {
          title: "Security",
          url: "#",
        },
        {
          title: "Integrations",
          url: "#",
        },
        {
          title: "Notifications",
          url: "#",
        },
        {
          title: "API Keys",
          url: "#",
        },
        {
          title: "Webhooks",
          url: "#",
        },
      ],
      title: "Settings",
      url: "#",
    },
  ],
  user: {
    email: "m@example.com",
    name: "Lumi UI",
  },
  versions: ["1.0.1", "1.1.0-alpha", "2.0.0-beta1"],
};
registry/blocks/sidebar-02/components/nav-main.tsx
"use client";

import { ChevronRight, type LucideIcon } from "lucide-react";
import {
  Collapsible,
  CollapsiblePanel,
  CollapsibleTrigger,
} from "@/registry/ui/collapsible";
import {
  SidebarGroup,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
} from "@/registry/ui/sidebar";

export function NavMain({
  items,
}: {
  items: {
    title: string;
    url: string;
    icon?: LucideIcon;
    isActive?: boolean;
    items?: {
      title: string;
      url: string;
    }[];
  }[];
}) {
  return (
    <SidebarGroup>
      <SidebarMenu>
        {items.map((item) => (
          <SidebarMenuItem key={item.title}>
            <Collapsible defaultOpen={item.isActive}>
              <CollapsibleTrigger
                className="group/collapsible data-[panel-open]:bg-sidebar-accent data-[panel-open]:text-sidebar-accent-foreground"
                render={
                  <SidebarMenuButton
                    tooltip={{
                      children: item.title,
                      side: "right",
                    }}
                  >
                    {item.icon && <item.icon />}
                    <span>{item.title}</span>
                    <ChevronRight className="ml-auto text-muted-foreground transition-[transform,colors] duration-200 group-data-[panel-open]/collapsible:rotate-90 group-data-[panel-open]/collapsible:text-foreground group-hover/collapsible:text-sidebar-foreground" />
                  </SidebarMenuButton>
                }
              />
              <CollapsiblePanel>
                <SidebarMenuSub>
                  {item.items?.map((subItem) => (
                    <SidebarMenuSubItem key={subItem.title}>
                      <SidebarMenuSubButton
                        render={
                          <a href={subItem.url}>
                            <span>{subItem.title}</span>
                          </a>
                        }
                      />
                    </SidebarMenuSubItem>
                  ))}
                </SidebarMenuSub>
              </CollapsiblePanel>
            </Collapsible>
          </SidebarMenuItem>
        ))}
      </SidebarMenu>
    </SidebarGroup>
  );
}
registry/blocks/sidebar-02/components/version-switcher.tsx
"use client";

import {
  BadgeCheckIcon,
  ChevronsUpDown,
  GalleryVerticalEnd,
} from "lucide-react";
import * as React from "react";
import {
  DropdownMenu,
  DropdownMenuCheckboxItemContent,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "@/registry/ui/dropdown-menu";
import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
} from "@/registry/ui/sidebar";

export function VersionSwitcher({
  versions,
  defaultVersion,
}: {
  versions: string[];
  defaultVersion: string;
}) {
  const [selectedVersion, setSelectedVersion] = React.useState(defaultVersion);

  return (
    <SidebarMenu>
      <SidebarMenuItem>
        <DropdownMenu>
          <DropdownMenuTrigger
            render={
              <SidebarMenuButton
                className="data-[popup-open]:bg-sidebar-accent data-[popup-open]:text-sidebar-accent-foreground justify-between px-2 gap-2"
                size="lg"
              >
                <span>
                  <GalleryVerticalEnd className="size-4" />
                </span>
                <div className="flex flex-col gap-1 leading-none">
                  <span className="font-medium">Documentation</span>
                  <span className="text-muted-foreground">
                    v{selectedVersion}
                  </span>
                </div>
                <ChevronsUpDown className="ml-auto" />
              </SidebarMenuButton>
            }
          />
          <DropdownMenuContent matchAnchorWidth>
            {versions.map((version) => (
              <DropdownMenuCheckboxItemContent
                checked={version === selectedVersion}
                closeOnClick
                indicatorIcon={<BadgeCheckIcon />}
                indicatorPlacement="end"
                key={version}
                onCheckedChange={() => setSelectedVersion(version)}
              >
                v{version}
              </DropdownMenuCheckboxItemContent>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
      </SidebarMenuItem>
    </SidebarMenu>
  );
}

More from lumiui

Browse all components in this library →