Sidebar structure

This commit is contained in:
2025-11-11 19:15:47 +01:00
parent 01aaca1ca2
commit 2ea4f34e7a
6 changed files with 136 additions and 5 deletions
+31
View File
@@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@hello-pangea/dnd": "^18.0.1", "@hello-pangea/dnd": "^18.0.1",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.8", "@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-popover": "^1.1.15",
@@ -801,6 +802,36 @@
} }
} }
}, },
"node_modules/@radix-ui/react-collapsible": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
"integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-id": "1.1.1",
"@radix-ui/react-presence": "1.1.5",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection": { "node_modules/@radix-ui/react-collection": {
"version": "1.1.7", "version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+1
View File
@@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@hello-pangea/dnd": "^18.0.1", "@hello-pangea/dnd": "^18.0.1",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.8", "@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-popover": "^1.1.15",
+1 -1
View File
@@ -1,6 +1,6 @@
"use client"; "use client";
import AppSidebar, { SidebarTrigger } from "@/components/AppSidebar"; import AppSidebar, { SidebarTrigger } from "@/components/sidebar/AppSidebar";
import BoardView from "@/components/view/board/BoardView"; import BoardView from "@/components/view/board/BoardView";
import TaskView from "@/components/view/TaskView"; import TaskView from "@/components/view/TaskView";
import { Task } from "@/lib/types"; import { Task } from "@/lib/types";
@@ -1,13 +1,21 @@
import { cn } from "@/lib/utils";
import { Button } from "./ui/button";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
SidebarFooter, SidebarFooter,
SidebarHeader, SidebarHeader,
SidebarMenu,
SidebarProvider, SidebarProvider,
useSidebar, useSidebar,
} from "./ui/sidebar"; } from "@/components/ui/sidebar";
import EntitySwitch, { Entity } from "./Entity";
const workspaceEntities: Entity[] = [
{
name: "Project alpha",
kind: "group",
children: [{ name: "Tasks", kind: "todo" }],
},
];
export default function AppSidebar({ export default function AppSidebar({
children, children,
@@ -18,7 +26,13 @@ export default function AppSidebar({
<SidebarProvider> <SidebarProvider>
<Sidebar> <Sidebar>
<SidebarHeader /> <SidebarHeader />
<SidebarContent></SidebarContent> <SidebarContent>
<SidebarMenu>
{workspaceEntities.map((entity, i) => (
<EntitySwitch entity={entity} key={i} />
))}
</SidebarMenu>
</SidebarContent>
<SidebarFooter /> <SidebarFooter />
</Sidebar> </Sidebar>
<main className="w-svw">{children}</main> <main className="w-svw">{children}</main>
+52
View File
@@ -0,0 +1,52 @@
import { CollapsibleTrigger } from "@radix-ui/react-collapsible";
import {
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "../ui/sidebar";
import { Collapsible, CollapsibleContent } from "../ui/collapsible";
import { ChevronDown } from "lucide-react";
export interface Entity {
name: string;
kind: "group" | "todo";
children?: Entity[];
}
export default function EntitySwitch({ entity }: { entity: Entity }) {
switch (entity.kind) {
case "group":
return (
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
<SidebarMenuButton asChild>
<CollapsibleTrigger>
{entity.name}
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarMenuButton>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{entity.children?.map((entity, i) => (
<EntitySwitch entity={entity} key={i} />
))}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
);
case "todo":
return (
<SidebarMenuItem>
<SidebarMenuButton>{entity.name}</SidebarMenuButton>
</SidebarMenuItem>
);
}
}
+33
View File
@@ -0,0 +1,33 @@
"use client"
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
function Collapsible({
...props
}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
}
function CollapsibleTrigger({
...props
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
return (
<CollapsiblePrimitive.CollapsibleTrigger
data-slot="collapsible-trigger"
{...props}
/>
)
}
function CollapsibleContent({
...props
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
return (
<CollapsiblePrimitive.CollapsibleContent
data-slot="collapsible-content"
{...props}
/>
)
}
export { Collapsible, CollapsibleTrigger, CollapsibleContent }