This commit is contained in:
2026-02-27 22:07:33 +01:00
parent 4823cca418
commit f856edc916
2 changed files with 67 additions and 43 deletions
+26 -19
View File
@@ -1,3 +1,5 @@
"use client";
import {
Sidebar,
SidebarContent,
@@ -8,25 +10,30 @@ import {
SidebarProvider,
useSidebar,
} from "@/components/ui/sidebar";
import EntitySwitch from "./Entity";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "../ui/dropdown-menu";
import { ChevronDown } from "lucide-react";
import { EntityId, Route, SetState, Workspace } from "@/lib/types";
import { Route, SetState, Workspace } from "@/lib/types";
type AppSidebarProps = {
children: React.ReactNode;
workspace: Workspace;
setRoute: SetState<Route>;
};
export default function AppSidebar({
children,
workspace,
setRoute,
}: Readonly<{
children: React.ReactNode;
workspace: Workspace;
setRoute: SetState<Route>;
}>) {
}: AppSidebarProps) {
return (
<SidebarProvider>
<Sidebar>
@@ -37,52 +44,52 @@ export default function AppSidebar({
<DropdownMenuTrigger asChild>
<button className="flex w-full items-center justify-between px-2 py-1 text-sm">
{workspace.name}
<ChevronDown className="ml-auto" />
<ChevronDown className="ml-auto h-4 w-4 opacity-60" />
</button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className="w-(--radix-popper-anchor-width)"
className="w-[--radix-popper-anchor-width]"
>
<DropdownMenuItem>Acme Inc</DropdownMenuItem>
<DropdownMenuItem>Acme Corp.</DropdownMenuItem>
{/* Future: real workspace switching */}
<DropdownMenuItem>Rename Workspace</DropdownMenuItem>
<DropdownMenuItem>Export Workspace</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarMenu>
{workspace.layout.map((entity, i) => (
{workspace.layout.map((entity) => (
<EntitySwitch
key={entity.id}
entity={entity}
workspace={workspace}
key={i}
setRoute={setRoute}
/>
))}
</SidebarMenu>
</SidebarContent>
<SidebarFooter />
</Sidebar>
<main className="w-svw">{children}</main>
</SidebarProvider>
);
}
export function SidebarTrigger({
className,
...props
}: React.ComponentProps<"div">) {
export function SidebarTrigger(props: React.ComponentProps<"div">) {
const { toggleSidebar } = useSidebar();
return (
<div
data-sidebar="trigger"
data-slot="sidebar-trigger"
onClick={(event) => {
toggleSidebar();
}}
onClick={toggleSidebar}
{...props}
/>
);
+41 -24
View File
@@ -1,3 +1,5 @@
"use client";
import { CollapsibleTrigger } from "@radix-ui/react-collapsible";
import {
SidebarGroup,
@@ -9,11 +11,12 @@ import {
} from "../ui/sidebar";
import { Collapsible, CollapsibleContent } from "../ui/collapsible";
import { ChevronDown } from "lucide-react";
import { EntityId, Route, SetState, Workspace } from "@/lib/types";
import { Route, Workspace } from "@/lib/types";
export type SidebarEntity =
| {
kind: "group";
id: string; // ✅ add stable id
name: string;
children: SidebarEntity[];
}
@@ -22,35 +25,39 @@ export type SidebarEntity =
id: string;
};
type Props = {
entity: SidebarEntity;
workspace: Workspace;
setRoute: (route: Route) => void;
};
export default function EntitySwitch({
entity,
workspace,
setRoute,
}: {
entity: SidebarEntity;
workspace: Workspace;
setRoute: SetState<Route>;
}) {
}: Props) {
// ---- GROUP ----
if (entity.kind === "group") {
return (
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
<SidebarMenuButton asChild>
<CollapsibleTrigger>
<CollapsibleTrigger className="flex w-full items-center">
{entity.name}
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
<ChevronDown className="ml-auto h-4 w-4 transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarMenuButton>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{entity.children?.map((entity, i) => (
{entity.children.map((child) => (
<EntitySwitch
entity={entity}
key={child.id} // ✅ stable key
entity={child}
workspace={workspace}
key={i}
setRoute={setRoute}
/>
))}
@@ -60,17 +67,27 @@ export default function EntitySwitch({
</SidebarGroup>
</Collapsible>
);
} else {
return (
<SidebarMenuItem>
<SidebarMenuButton
onClick={() => {
setRoute({ workspace: workspace.id, entity: entity.id });
}}
>
{workspace.entities[entity.id].name}
</SidebarMenuButton>
</SidebarMenuItem>
);
}
}
// ---- ITEM ----
const workspaceEntity = workspace.entities[entity.id];
if (!workspaceEntity) {
return null; // defensive against stale layout
}
return (
<SidebarMenuItem>
<SidebarMenuButton
onClick={() =>
setRoute({
workspace: workspace.id,
entity: entity.id,
})
}
>
{workspaceEntity.name}
</SidebarMenuButton>
</SidebarMenuItem>
);
}