snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
All checks were successful
Release / Create Version PR or Publish Stable Release (push) Has been skipped
Release / Publish Prerelease to NPM (push) Has been skipped
Monitor Registries / Monitor registry health (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-15 22:44:43 +05:00
commit 1416db152c
5727 changed files with 630238 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
import { type Registry } from "shadcn/schema"
export const internal: Registry["items"] = [
// Do not move this. They are intentionally here for registry capture.
{
name: "sidebar-demo",
type: "registry:internal",
files: [
{
path: "internal/sidebar-demo.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-header",
type: "registry:internal",
files: [
{
path: "internal/sidebar-header.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-footer",
type: "registry:internal",
files: [
{
path: "internal/sidebar-footer.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-group",
type: "registry:internal",
files: [
{
path: "internal/sidebar-group.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-group-collapsible",
type: "registry:internal",
files: [
{
path: "internal/sidebar-group-collapsible.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-group-action",
type: "registry:internal",
files: [
{
path: "internal/sidebar-group-action.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-menu",
type: "registry:internal",
files: [
{
path: "internal/sidebar-menu.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-menu-action",
type: "registry:internal",
files: [
{
path: "internal/sidebar-menu-action.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-menu-sub",
type: "registry:internal",
files: [
{
path: "internal/sidebar-menu-sub.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-menu-collapsible",
type: "registry:internal",
files: [
{
path: "internal/sidebar-menu-collapsible.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-menu-badge",
type: "registry:internal",
files: [
{
path: "internal/sidebar-menu-badge.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-rsc",
type: "registry:internal",
files: [
{
path: "internal/sidebar-rsc.tsx",
type: "registry:component",
},
],
},
{
name: "sidebar-controlled",
type: "registry:internal",
files: [
{
path: "internal/sidebar-controlled.tsx",
type: "registry:component",
},
],
},
]

View File

@@ -0,0 +1,96 @@
"use client"
import * as React from "react"
import {
FrameIcon,
LifeBuoyIcon,
MapIcon,
PanelLeftCloseIcon,
PanelLeftOpenIcon,
PieChartIcon,
SendIcon,
} from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: FrameIcon,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChartIcon,
},
{
name: "Travel",
url: "#",
icon: MapIcon,
},
{
name: "Support",
url: "#",
icon: LifeBuoyIcon,
},
{
name: "Feedback",
url: "#",
icon: SendIcon,
},
]
export default function AppSidebar() {
const [open, setOpen] = React.useState(true)
return (
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<header className="flex h-12 items-center justify-between px-4">
<Button
onClick={() => setOpen((open) => !open)}
size="sm"
variant="ghost"
>
{open ? <PanelLeftCloseIcon /> : <PanelLeftOpenIcon />}
<span>{open ? "Close" : "Open"} Sidebar</span>
</Button>
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,85 @@
"use client"
import {
CalendarIcon,
HomeIcon,
InboxIcon,
SearchIcon,
SettingsIcon,
} from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/new-york-v4/ui/sidebar"
// Menu items.
const items = [
{
title: "Home",
url: "#",
icon: HomeIcon,
},
{
title: "Inbox",
url: "#",
icon: InboxIcon,
},
{
title: "Calendar",
url: "#",
icon: CalendarIcon,
},
{
title: "Search",
url: "#",
icon: SearchIcon,
},
{
title: "Settings",
url: "#",
icon: SettingsIcon,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<header className="flex h-12 items-center justify-between px-4">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,66 @@
"use client"
import { ChevronUpIcon } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/new-york-v4/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader />
<SidebarContent />
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
Username
<ChevronUpIcon className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side="top"
className="w-(--radix-popper-anchor-width)"
>
<DropdownMenuItem>
<span>Account</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Billing</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Sign out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>
<SidebarInset>
<header className="flex h-12 items-center justify-between px-4">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,71 @@
"use client"
import { FrameIcon, MapIcon, PieChartIcon, PlusIcon } from "lucide-react"
import { toast, Toaster } from "sonner"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Toaster
position="bottom-left"
toastOptions={{
className: "ml-[160px]",
}}
/>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupAction
title="Add Project"
onClick={() => toast("You clicked the group action!")}
>
<PlusIcon /> <span className="sr-only">Add Project</span>
</SidebarGroupAction>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<FrameIcon />
<span>Design Engineering</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<PieChartIcon />
<span>Sales & Marketing</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<MapIcon />
<span>Travel</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,62 @@
"use client"
import { ChevronDownIcon, LifeBuoyIcon, SendIcon } from "lucide-react"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/new-york-v4/ui/collapsible"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel
asChild
className="text-sm hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
>
<CollapsibleTrigger>
Help
<ChevronDownIcon className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<LifeBuoyIcon />
Support
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<SendIcon />
Feedback
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,45 @@
"use client"
import { LifeBuoyIcon, SendIcon } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Help</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<LifeBuoyIcon />
Support
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<SendIcon />
Feedback
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,56 @@
"use client"
import { ChevronDownIcon } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
import {
Sidebar,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/registry/new-york-v4/ui/sidebar"
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
Select Workspace
<ChevronDownIcon className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-(--radix-popper-anchor-width)">
<DropdownMenuItem>
<span>Acme Inc</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Acme Corp.</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
</Sidebar>
<SidebarInset>
<header className="flex h-12 items-center justify-between px-4">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,104 @@
"use client"
import {
FrameIcon,
LifeBuoyIcon,
MapIcon,
MoreHorizontalIcon,
PieChartIcon,
SendIcon,
} from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuAction,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: FrameIcon,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChartIcon,
},
{
name: "Travel",
url: "#",
icon: MapIcon,
},
{
name: "Support",
url: "#",
icon: LifeBuoyIcon,
},
{
name: "Feedback",
url: "#",
icon: SendIcon,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton
asChild
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuAction>
<MoreHorizontalIcon />
<span className="sr-only">More</span>
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
<DropdownMenuItem>
<span>Edit Project</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Delete Project</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,87 @@
"use client"
import {
FrameIcon,
LifeBuoyIcon,
MapIcon,
PieChartIcon,
SendIcon,
} from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: FrameIcon,
badge: "24",
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChartIcon,
badge: "12",
},
{
name: "Travel",
url: "#",
icon: MapIcon,
badge: "3",
},
{
name: "Support",
url: "#",
icon: LifeBuoyIcon,
badge: "21",
},
{
name: "Feedback",
url: "#",
icon: SendIcon,
badge: "8",
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton
asChild
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
<SidebarMenuBadge>{project.badge}</SidebarMenuBadge>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,196 @@
"use client"
import { ChevronRightIcon } from "lucide-react"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/new-york-v4/ui/collapsible"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const items = [
{
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: "#",
},
],
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item, index) => (
<Collapsible
key={index}
className="group/collapsible"
defaultOpen={index === 0}
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<span>{item.title}</span>
<ChevronRightIcon className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items.map((subItem, subIndex) => (
<SidebarMenuSubItem key={subIndex}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,180 @@
"use client"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const items = [
{
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: "#",
},
],
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuButton asChild>
<a href={item.url}>
<span>{item.title}</span>
</a>
</SidebarMenuButton>
<SidebarMenuSub>
{item.items.map((subItem, subIndex) => (
<SidebarMenuSubItem key={subIndex}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,77 @@
"use client"
import {
FrameIcon,
LifeBuoyIcon,
MapIcon,
PieChartIcon,
SendIcon,
} from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: FrameIcon,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChartIcon,
},
{
name: "Travel",
url: "#",
icon: MapIcon,
},
{
name: "Support",
url: "#",
icon: LifeBuoyIcon,
},
{
name: "Feedback",
url: "#",
icon: SendIcon,
},
]
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -0,0 +1,110 @@
import * as React from "react"
import {
FrameIcon,
LifeBuoyIcon,
MapIcon,
PieChartIcon,
SendIcon,
} from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarProvider,
} from "@/registry/new-york-v4/ui/sidebar"
const projects = [
{
name: "Design Engineering",
url: "#",
icon: FrameIcon,
badge: "24",
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChartIcon,
badge: "12",
},
{
name: "Travel",
url: "#",
icon: MapIcon,
badge: "3",
},
{
name: "Support",
url: "#",
icon: LifeBuoyIcon,
badge: "21",
},
{
name: "Feedback",
url: "#",
icon: SendIcon,
badge: "8",
},
]
// Dummy fetch function
async function fetchProjects() {
await new Promise((resolve) => setTimeout(resolve, 3000))
return projects
}
export default function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<React.Suspense fallback={<NavProjectsSkeleton />}>
<NavProjects />
</React.Suspense>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
function NavProjectsSkeleton() {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton showIcon />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}
async function NavProjects() {
const projects = await fetchProjects()
return (
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
)
}