mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-01 08:34:12 +00:00
feat: add docs for sidebar
This commit is contained in:
@@ -4,7 +4,11 @@ import { type Metadata } from "next"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { siteConfig } from "@/lib/config"
|
||||
import { getRegistryComponent, getRegistryItem } from "@/lib/registry"
|
||||
import {
|
||||
getDemoItem,
|
||||
getRegistryComponent,
|
||||
getRegistryItem,
|
||||
} from "@/lib/registry"
|
||||
import { absoluteUrl } from "@/lib/utils"
|
||||
import { getStyle, legacyStyles, type Style } from "@/registry/_legacy-styles"
|
||||
|
||||
@@ -18,7 +22,12 @@ export const dynamicParams = false
|
||||
|
||||
const getCachedRegistryItem = React.cache(
|
||||
async (name: string, styleName: Style["name"]) => {
|
||||
return await getRegistryItem(name, styleName)
|
||||
// Try registry item first, then fallback to demo item (for examples).
|
||||
const item = await getRegistryItem(name, styleName)
|
||||
if (item) {
|
||||
return item
|
||||
}
|
||||
return await getDemoItem(name, styleName)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -75,9 +84,52 @@ export async function generateMetadata({
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const { Index } = await import("@/registry/__index__")
|
||||
const { Index: BasesIndex } = await import("@/registry/bases/__index__")
|
||||
const { ExamplesIndex } = await import("@/examples/__index__")
|
||||
const params: Array<{ style: string; name: string }> = []
|
||||
|
||||
for (const style of legacyStyles) {
|
||||
// Check if this is a base-prefixed style (e.g., base-nova, radix-nova).
|
||||
const baseMatch = style.name.match(/^(base|radix)-/)
|
||||
if (baseMatch) {
|
||||
const baseName = baseMatch[1]
|
||||
|
||||
// Add examples from ExamplesIndex.
|
||||
const examples = ExamplesIndex[baseName]
|
||||
if (examples) {
|
||||
for (const exampleName of Object.keys(examples)) {
|
||||
params.push({
|
||||
style: style.name,
|
||||
name: exampleName,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Add UI components from BasesIndex.
|
||||
const baseIndex = BasesIndex[baseName]
|
||||
if (baseIndex) {
|
||||
for (const itemName in baseIndex) {
|
||||
const item = baseIndex[itemName]
|
||||
if (
|
||||
[
|
||||
"registry:block",
|
||||
"registry:component",
|
||||
"registry:example",
|
||||
"registry:internal",
|
||||
].includes(item.type)
|
||||
) {
|
||||
params.push({
|
||||
style: style.name,
|
||||
name: item.name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle legacy styles (e.g., new-york-v4).
|
||||
if (!Index[style.name]) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ export function ComponentPreview({
|
||||
return (
|
||||
<div className="relative aspect-[4/2.5] w-full overflow-hidden rounded-xl border md:-mx-1">
|
||||
<Image
|
||||
src={`/r/styles/new-york-v4/${name}-light.png`}
|
||||
src={`/r/styles/${styleName}/${name}-light.png`}
|
||||
alt={name}
|
||||
width={1440}
|
||||
height={900}
|
||||
className="bg-background absolute top-0 left-0 z-20 w-[970px] max-w-none sm:w-[1280px] md:hidden dark:hidden md:dark:hidden"
|
||||
/>
|
||||
<Image
|
||||
src={`/r/styles/new-york-v4/${name}-dark.png`}
|
||||
src={`/r/styles/${styleName}/${name}-dark.png`}
|
||||
alt={name}
|
||||
width={1440}
|
||||
height={900}
|
||||
@@ -63,8 +63,6 @@ export function ComponentPreview({
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ComponentPreviewTabs
|
||||
className={className}
|
||||
|
||||
@@ -6,11 +6,7 @@ component: true
|
||||
---
|
||||
|
||||
<figure className="flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-07"
|
||||
type="block"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-demo" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar that collapses to icons.
|
||||
</figcaption>
|
||||
@@ -318,15 +314,8 @@ export function AppSidebar() {
|
||||
|
||||
You should see something like this:
|
||||
|
||||
<figure className="flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-demo"
|
||||
title="Sidebar"
|
||||
type="block"
|
||||
description="Your first sidebar."
|
||||
className="w-full"
|
||||
/>
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-demo" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
Your first sidebar.
|
||||
</figcaption>
|
||||
@@ -545,14 +534,7 @@ Use the `SidebarHeader` component to add a sticky header to the sidebar.
|
||||
The following example adds a `<DropdownMenu>` to the `SidebarHeader`.
|
||||
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-header"
|
||||
title="Sidebar"
|
||||
type="block"
|
||||
description="A sidebar header with a dropdown menu."
|
||||
className="w-full"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-header" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar header with a dropdown menu.
|
||||
</figcaption>
|
||||
@@ -592,14 +574,7 @@ Use the `SidebarFooter` component to add a sticky footer to the sidebar.
|
||||
The following example adds a `<DropdownMenu>` to the `SidebarFooter`.
|
||||
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-footer"
|
||||
title="Sidebar"
|
||||
type="block"
|
||||
description="A sidebar footer with a dropdown menu."
|
||||
className="w-full"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-footer" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar footer with a dropdown menu.
|
||||
</figcaption>
|
||||
@@ -672,14 +647,7 @@ Use the `SidebarGroup` component to create a section within the sidebar.
|
||||
A `SidebarGroup` has a `SidebarGroupLabel`, a `SidebarGroupContent` and an optional `SidebarGroupAction`.
|
||||
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-group"
|
||||
title="Sidebar Group"
|
||||
type="block"
|
||||
description="A sidebar group."
|
||||
className="w-full"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-group" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar group.
|
||||
</figcaption>
|
||||
@@ -713,10 +681,7 @@ To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-group-collapsible"
|
||||
title="Sidebar Group"
|
||||
type="block"
|
||||
description="A collapsible sidebar group."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A collapsible sidebar group.
|
||||
@@ -756,10 +721,7 @@ Use the `SidebarGroupAction` component to add an action button to the `SidebarGr
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-group-action"
|
||||
title="Sidebar Group"
|
||||
type="block"
|
||||
description="A sidebar group with an action button."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar group with an action button.
|
||||
@@ -804,14 +766,7 @@ A `SidebarMenu` component is composed of `SidebarMenuItem`, `SidebarMenuButton`,
|
||||
Here's an example of a `SidebarMenu` component rendering a list of projects.
|
||||
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-menu"
|
||||
title="Sidebar Menu"
|
||||
type="block"
|
||||
description="A sidebar menu with a list of projects."
|
||||
className="w-full"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-menu" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar menu with a list of projects.
|
||||
</figcaption>
|
||||
@@ -906,10 +861,7 @@ Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-menu-action"
|
||||
title="Sidebar Menu Action"
|
||||
type="block"
|
||||
description="A sidebar menu action with a dropdown menu."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar menu action with a dropdown menu.
|
||||
@@ -952,10 +904,7 @@ Use `<SidebarMenuSubItem />` and `<SidebarMenuSubButton />` to render a submenu
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-menu-sub"
|
||||
title="Sidebar Menu Sub"
|
||||
type="block"
|
||||
description="A sidebar menu sub."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar menu with a submenu.
|
||||
@@ -984,10 +933,7 @@ To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub`
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-menu-collapsible"
|
||||
title="Sidebar Menu"
|
||||
type="block"
|
||||
description="A collapsible sidebar menu."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A collapsible sidebar menu.
|
||||
@@ -1019,10 +965,7 @@ The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenu
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-menu-badge"
|
||||
title="Sidebar Menu Badge"
|
||||
type="block"
|
||||
description="A sidebar menu badge."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar menu with a badge.
|
||||
@@ -1121,14 +1064,7 @@ The `SidebarRail` component is used to render a rail within a `Sidebar`. This ra
|
||||
Here's an example of a `SidebarMenu` component rendering a list of projects using React Server Components.
|
||||
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-rsc"
|
||||
title="Sidebar Menu RSC"
|
||||
type="block"
|
||||
description="A sidebar menu using React Server Components."
|
||||
className="w-full"
|
||||
/>
|
||||
<ComponentPreview styleName="base-nova" name="sidebar-rsc" type="block" />
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A sidebar menu using React Server Components.
|
||||
</figcaption>
|
||||
@@ -1274,10 +1210,7 @@ Use the `open` and `onOpenChange` props to control the sidebar.
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="sidebar-controlled"
|
||||
title="Sidebar Controlled"
|
||||
type="block"
|
||||
description="A controlled sidebar."
|
||||
className="w-full"
|
||||
/>
|
||||
<figcaption className="text-center text-sm text-gray-500">
|
||||
A controlled sidebar.
|
||||
|
||||
@@ -321,7 +321,7 @@ export function AppSidebar() {
|
||||
|
||||
You should see something like this:
|
||||
|
||||
<figure className="flex flex-col gap-4">
|
||||
<figure className="mt-6 flex flex-col gap-4">
|
||||
<ComponentPreview
|
||||
styleName="radix-nova"
|
||||
name="sidebar-demo"
|
||||
|
||||
@@ -3827,6 +3827,175 @@ export const ExamplesIndex: Record<string, Record<string, any>> = {
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-controlled": {
|
||||
name: "sidebar-controlled",
|
||||
filePath: "examples/radix/sidebar-controlled.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-controlled")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-controlled"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-demo": {
|
||||
name: "sidebar-demo",
|
||||
filePath: "examples/radix/sidebar-demo.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-demo")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-demo"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-footer": {
|
||||
name: "sidebar-footer",
|
||||
filePath: "examples/radix/sidebar-footer.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-footer")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-footer"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group-action": {
|
||||
name: "sidebar-group-action",
|
||||
filePath: "examples/radix/sidebar-group-action.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-group-action")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group-action"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group-collapsible": {
|
||||
name: "sidebar-group-collapsible",
|
||||
filePath: "examples/radix/sidebar-group-collapsible.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-group-collapsible")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group-collapsible"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group": {
|
||||
name: "sidebar-group",
|
||||
filePath: "examples/radix/sidebar-group.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-group")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-header": {
|
||||
name: "sidebar-header",
|
||||
filePath: "examples/radix/sidebar-header.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-header")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-header"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-action": {
|
||||
name: "sidebar-menu-action",
|
||||
filePath: "examples/radix/sidebar-menu-action.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-menu-action")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-action"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-badge": {
|
||||
name: "sidebar-menu-badge",
|
||||
filePath: "examples/radix/sidebar-menu-badge.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-menu-badge")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-badge"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-collapsible": {
|
||||
name: "sidebar-menu-collapsible",
|
||||
filePath: "examples/radix/sidebar-menu-collapsible.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-menu-collapsible")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-collapsible"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-sub": {
|
||||
name: "sidebar-menu-sub",
|
||||
filePath: "examples/radix/sidebar-menu-sub.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-menu-sub")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-sub"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu": {
|
||||
name: "sidebar-menu",
|
||||
filePath: "examples/radix/sidebar-menu.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-menu")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-rsc": {
|
||||
name: "sidebar-rsc",
|
||||
filePath: "examples/radix/sidebar-rsc.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./radix/sidebar-rsc")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-rsc"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"skeleton-avatar": {
|
||||
name: "skeleton-avatar",
|
||||
filePath: "examples/radix/skeleton-avatar.tsx",
|
||||
@@ -8548,6 +8717,175 @@ export const ExamplesIndex: Record<string, Record<string, any>> = {
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-controlled": {
|
||||
name: "sidebar-controlled",
|
||||
filePath: "examples/base/sidebar-controlled.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-controlled")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-controlled"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-demo": {
|
||||
name: "sidebar-demo",
|
||||
filePath: "examples/base/sidebar-demo.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-demo")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-demo"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-footer": {
|
||||
name: "sidebar-footer",
|
||||
filePath: "examples/base/sidebar-footer.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-footer")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-footer"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group-action": {
|
||||
name: "sidebar-group-action",
|
||||
filePath: "examples/base/sidebar-group-action.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-group-action")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group-action"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group-collapsible": {
|
||||
name: "sidebar-group-collapsible",
|
||||
filePath: "examples/base/sidebar-group-collapsible.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-group-collapsible")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group-collapsible"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-group": {
|
||||
name: "sidebar-group",
|
||||
filePath: "examples/base/sidebar-group.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-group")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-group"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-header": {
|
||||
name: "sidebar-header",
|
||||
filePath: "examples/base/sidebar-header.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-header")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-header"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-action": {
|
||||
name: "sidebar-menu-action",
|
||||
filePath: "examples/base/sidebar-menu-action.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-menu-action")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-action"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-badge": {
|
||||
name: "sidebar-menu-badge",
|
||||
filePath: "examples/base/sidebar-menu-badge.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-menu-badge")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-badge"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-collapsible": {
|
||||
name: "sidebar-menu-collapsible",
|
||||
filePath: "examples/base/sidebar-menu-collapsible.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-menu-collapsible")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-collapsible"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu-sub": {
|
||||
name: "sidebar-menu-sub",
|
||||
filePath: "examples/base/sidebar-menu-sub.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-menu-sub")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu-sub"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-menu": {
|
||||
name: "sidebar-menu",
|
||||
filePath: "examples/base/sidebar-menu.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-menu")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-menu"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"sidebar-rsc": {
|
||||
name: "sidebar-rsc",
|
||||
filePath: "examples/base/sidebar-rsc.tsx",
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("./base/sidebar-rsc")
|
||||
const exportName =
|
||||
Object.keys(mod).find(
|
||||
(key) =>
|
||||
typeof mod[key] === "function" || typeof mod[key] === "object"
|
||||
) || "sidebar-rsc"
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
},
|
||||
"skeleton-avatar": {
|
||||
name: "skeleton-avatar",
|
||||
filePath: "examples/base/skeleton-avatar.tsx",
|
||||
|
||||
93
apps/v4/examples/base/sidebar-controlled.tsx
Normal file
93
apps/v4/examples/base/sidebar-controlled.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PanelLeftCloseIcon,
|
||||
PanelLeftOpenIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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 render={<a href={project.url} />}>
|
||||
<project.icon />
|
||||
<span>{project.name}</span>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
81
apps/v4/examples/base/sidebar-demo.tsx
Normal file
81
apps/v4/examples/base/sidebar-demo.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
CalendarIcon,
|
||||
HomeIcon,
|
||||
InboxIcon,
|
||||
SearchIcon,
|
||||
SettingsIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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 render={<a href={item.url} />}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
<SidebarInset>
|
||||
<header className="flex h-12 items-center justify-between px-4">
|
||||
<SidebarTrigger />
|
||||
</header>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
67
apps/v4/examples/base/sidebar-footer.tsx
Normal file
67
apps/v4/examples/base/sidebar-footer.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { ChevronUpIcon } from "lucide-react"
|
||||
|
||||
export default function AppSidebar() {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<Sidebar>
|
||||
<SidebarHeader />
|
||||
<SidebarContent />
|
||||
<SidebarFooter>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" />
|
||||
}
|
||||
>
|
||||
Username
|
||||
<ChevronUpIcon className="ml-auto" />
|
||||
</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>
|
||||
)
|
||||
}
|
||||
64
apps/v4/examples/base/sidebar-group-action.tsx
Normal file
64
apps/v4/examples/base/sidebar-group-action.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupAction,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { FrameIcon, MapIcon, PieChartIcon, PlusIcon } from "lucide-react"
|
||||
import { toast, Toaster } from "sonner"
|
||||
|
||||
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 render={<a href="#" />}>
|
||||
<FrameIcon />
|
||||
<span>Design Engineering</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton render={<a href="#" />}>
|
||||
<PieChartIcon />
|
||||
<span>Sales & Marketing</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton render={<a href="#" />}>
|
||||
<MapIcon />
|
||||
<span>Travel</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
59
apps/v4/examples/base/sidebar-group-collapsible.tsx
Normal file
59
apps/v4/examples/base/sidebar-group-collapsible.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/examples/base/ui/collapsible"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { ChevronDownIcon, LifeBuoyIcon, SendIcon } from "lucide-react"
|
||||
|
||||
export default function AppSidebar() {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<Sidebar>
|
||||
<SidebarContent>
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel
|
||||
render={<CollapsibleTrigger />}
|
||||
className="hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm"
|
||||
>
|
||||
Help
|
||||
<ChevronDownIcon className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
||||
</SidebarGroupLabel>
|
||||
<CollapsibleContent>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton>
|
||||
<LifeBuoyIcon />
|
||||
Support
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton>
|
||||
<SendIcon />
|
||||
Feedback
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</CollapsibleContent>
|
||||
</SidebarGroup>
|
||||
</Collapsible>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
44
apps/v4/examples/base/sidebar-group.tsx
Normal file
44
apps/v4/examples/base/sidebar-group.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { LifeBuoyIcon, SendIcon } from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
57
apps/v4/examples/base/sidebar-header.tsx
Normal file
57
apps/v4/examples/base/sidebar-header.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { ChevronDownIcon } from "lucide-react"
|
||||
|
||||
export default function AppSidebar() {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<Sidebar>
|
||||
<SidebarHeader>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
render={
|
||||
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" />
|
||||
}
|
||||
>
|
||||
Select Workspace
|
||||
<ChevronDownIcon className="ml-auto" />
|
||||
</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>
|
||||
)
|
||||
}
|
||||
99
apps/v4/examples/base/sidebar-menu-action.tsx
Normal file
99
apps/v4/examples/base/sidebar-menu-action.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuAction,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
MoreHorizontalIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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
|
||||
render={<a href={project.url} />}
|
||||
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
|
||||
>
|
||||
<project.icon />
|
||||
<span>{project.name}</span>
|
||||
</SidebarMenuButton>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger render={<SidebarMenuAction />}>
|
||||
<MoreHorizontalIcon />
|
||||
<span className="sr-only">More</span>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
84
apps/v4/examples/base/sidebar-menu-badge.tsx
Normal file
84
apps/v4/examples/base/sidebar-menu-badge.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuBadge,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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
|
||||
render={<a href={project.url} />}
|
||||
className="group-has-[[data-state=open]]/menu-item:bg-sidebar-accent"
|
||||
>
|
||||
<project.icon />
|
||||
<span>{project.name}</span>
|
||||
</SidebarMenuButton>
|
||||
<SidebarMenuBadge>{project.badge}</SidebarMenuBadge>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
193
apps/v4/examples/base/sidebar-menu-collapsible.tsx
Normal file
193
apps/v4/examples/base/sidebar-menu-collapsible.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/examples/base/ui/collapsible"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { ChevronRightIcon } from "lucide-react"
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
url: "#",
|
||||
items: [
|
||||
{
|
||||
title: "Installation",
|
||||
url: "#",
|
||||
},
|
||||
{
|
||||
title: "Project Structure",
|
||||
url: "#",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Building 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 render={<SidebarMenuButton />}>
|
||||
<span>{item.title}</span>
|
||||
<ChevronRightIcon className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((subItem, subIndex) => (
|
||||
<SidebarMenuSubItem key={subIndex}>
|
||||
<SidebarMenuSubButton
|
||||
render={<a href={subItem.url} />}
|
||||
>
|
||||
<span>{subItem.title}</span>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
178
apps/v4/examples/base/sidebar-menu-sub.tsx
Normal file
178
apps/v4/examples/base/sidebar-menu-sub.tsx
Normal file
@@ -0,0 +1,178 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
url: "#",
|
||||
items: [
|
||||
{
|
||||
title: "Installation",
|
||||
url: "#",
|
||||
},
|
||||
{
|
||||
title: "Project Structure",
|
||||
url: "#",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Building 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 render={<a href={item.url} />}>
|
||||
<span>{item.title}</span>
|
||||
</SidebarMenuButton>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((subItem, subIndex) => (
|
||||
<SidebarMenuSubItem key={subIndex}>
|
||||
<SidebarMenuSubButton
|
||||
render={<a href={subItem.url} />}
|
||||
>
|
||||
<span>{subItem.title}</span>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
74
apps/v4/examples/base/sidebar-menu.tsx
Normal file
74
apps/v4/examples/base/sidebar-menu.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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 render={<a href={project.url} />}>
|
||||
<project.icon />
|
||||
<span>{project.name}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
107
apps/v4/examples/base/sidebar-rsc.tsx
Normal file
107
apps/v4/examples/base/sidebar-rsc.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import * as React from "react"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSkeleton,
|
||||
SidebarProvider,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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 render={<a href={project.url} />}>
|
||||
<project.icon />
|
||||
<span>{project.name}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
)
|
||||
}
|
||||
@@ -27,7 +27,7 @@ function NavigationMenu({
|
||||
function NavigationMenuList({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.List.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.List
|
||||
data-slot="navigation-menu-list"
|
||||
@@ -43,7 +43,7 @@ function NavigationMenuList({
|
||||
function NavigationMenuItem({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.Item.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.Item
|
||||
data-slot="navigation-menu-item"
|
||||
@@ -146,7 +146,7 @@ function NavigationMenuLink({
|
||||
function NavigationMenuIndicator({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.Icon.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Icon>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.Icon
|
||||
data-slot="navigation-menu-indicator"
|
||||
|
||||
95
apps/v4/examples/radix/sidebar-controlled.tsx
Normal file
95
apps/v4/examples/radix/sidebar-controlled.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PanelLeftCloseIcon,
|
||||
PanelLeftOpenIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
83
apps/v4/examples/radix/sidebar-demo.tsx
Normal file
83
apps/v4/examples/radix/sidebar-demo.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
CalendarIcon,
|
||||
HomeIcon,
|
||||
InboxIcon,
|
||||
SearchIcon,
|
||||
SettingsIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
65
apps/v4/examples/radix/sidebar-footer.tsx
Normal file
65
apps/v4/examples/radix/sidebar-footer.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { ChevronUpIcon } from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
70
apps/v4/examples/radix/sidebar-group-action.tsx
Normal file
70
apps/v4/examples/radix/sidebar-group-action.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupAction,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { FrameIcon, MapIcon, PieChartIcon, PlusIcon } from "lucide-react"
|
||||
import { toast, Toaster } from "sonner"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
61
apps/v4/examples/radix/sidebar-group-collapsible.tsx
Normal file
61
apps/v4/examples/radix/sidebar-group-collapsible.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/examples/radix/ui/collapsible"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { ChevronDownIcon, LifeBuoyIcon, SendIcon } from "lucide-react"
|
||||
|
||||
export default function AppSidebar() {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<Sidebar>
|
||||
<SidebarContent>
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel
|
||||
asChild
|
||||
className="hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm"
|
||||
>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
44
apps/v4/examples/radix/sidebar-group.tsx
Normal file
44
apps/v4/examples/radix/sidebar-group.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { LifeBuoyIcon, SendIcon } from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
55
apps/v4/examples/radix/sidebar-header.tsx
Normal file
55
apps/v4/examples/radix/sidebar-header.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { ChevronDownIcon } from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
103
apps/v4/examples/radix/sidebar-menu-action.tsx
Normal file
103
apps/v4/examples/radix/sidebar-menu-action.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuAction,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
MoreHorizontalIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
86
apps/v4/examples/radix/sidebar-menu-badge.tsx
Normal file
86
apps/v4/examples/radix/sidebar-menu-badge.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuBadge,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
195
apps/v4/examples/radix/sidebar-menu-collapsible.tsx
Normal file
195
apps/v4/examples/radix/sidebar-menu-collapsible.tsx
Normal file
@@ -0,0 +1,195 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/examples/radix/ui/collapsible"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import { ChevronRightIcon } from "lucide-react"
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
url: "#",
|
||||
items: [
|
||||
{
|
||||
title: "Installation",
|
||||
url: "#",
|
||||
},
|
||||
{
|
||||
title: "Project Structure",
|
||||
url: "#",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Building 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>
|
||||
)
|
||||
}
|
||||
180
apps/v4/examples/radix/sidebar-menu-sub.tsx
Normal file
180
apps/v4/examples/radix/sidebar-menu-sub.tsx
Normal file
@@ -0,0 +1,180 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
url: "#",
|
||||
items: [
|
||||
{
|
||||
title: "Installation",
|
||||
url: "#",
|
||||
},
|
||||
{
|
||||
title: "Project Structure",
|
||||
url: "#",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Building 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>
|
||||
)
|
||||
}
|
||||
76
apps/v4/examples/radix/sidebar-menu.tsx
Normal file
76
apps/v4/examples/radix/sidebar-menu.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
109
apps/v4/examples/radix/sidebar-rsc.tsx
Normal file
109
apps/v4/examples/radix/sidebar-rsc.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import * as React from "react"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSkeleton,
|
||||
SidebarProvider,
|
||||
} from "@/examples/radix/ui/sidebar"
|
||||
import {
|
||||
FrameIcon,
|
||||
LifeBuoyIcon,
|
||||
MapIcon,
|
||||
PieChartIcon,
|
||||
SendIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -3,6 +3,14 @@ export const legacyStyles = [
|
||||
name: "new-york-v4",
|
||||
title: "New York",
|
||||
},
|
||||
{
|
||||
name: "base-nova",
|
||||
title: "Base Nova",
|
||||
},
|
||||
{
|
||||
name: "radix-nova",
|
||||
title: "Radix Nova",
|
||||
},
|
||||
] as const
|
||||
|
||||
export type Style = (typeof legacyStyles)[number]
|
||||
|
||||
@@ -27,7 +27,7 @@ function NavigationMenu({
|
||||
function NavigationMenuList({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.List.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.List
|
||||
data-slot="navigation-menu-list"
|
||||
@@ -43,7 +43,7 @@ function NavigationMenuList({
|
||||
function NavigationMenuItem({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.Item.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.Item
|
||||
data-slot="navigation-menu-item"
|
||||
@@ -143,7 +143,7 @@ function NavigationMenuLink({
|
||||
function NavigationMenuIndicator({
|
||||
className,
|
||||
...props
|
||||
}: NavigationMenuPrimitive.Icon.Props) {
|
||||
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Icon>) {
|
||||
return (
|
||||
<NavigationMenuPrimitive.Icon
|
||||
data-slot="navigation-menu-indicator"
|
||||
|
||||
Reference in New Issue
Block a user