import { useState } from 'react';
import { Link, useRouterState } from '@tanstack/react-router';
import {
House,
ChartGantt,
ClipboardCheck,
FolderKanban,
PanelLeft,
ChevronUp,
} from 'lucide-react';
import { trpc } from '@/lib/trpc';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
useSidebar,
} from '@/components/ui/sidebar';
const NAV_ITEMS = [
{ to: '/', icon: House, label: 'Home' },
{ to: '/timeline', icon: ChartGantt, label: 'Timeline' },
{ to: '/tasks', icon: ClipboardCheck, label: 'Tasks' },
{ to: '/projects', icon: FolderKanban, label: 'Projects' },
] as const;
interface AppShellProps {
children: React.ReactNode;
}
export function AppShell({ children }: AppShellProps) {
const collapsedQuery = trpc.settings.getSidebarCollapsed.useQuery(undefined, {
staleTime: Infinity,
});
const setSidebarCollapsedMutation = trpc.settings.setSidebarCollapsed.useMutation();
const routerState = useRouterState();
const currentPath = routerState.location.pathname;
// Controlled open state (spec: "Controlled Sidebar" pattern)
const [open, setOpen] = useState(() =>
collapsedQuery.data === undefined ? true : !collapsedQuery.data
);
const handleOpenChange = (value: boolean) => {
setOpen(value);
setSidebarCollapsedMutation.mutate({ collapsed: !value });
};
return (
{children}
{/* Right-edge vertical 'keep scrolling for AI' affordance (non-interactive) */}
);
}
function AppSidebar({ currentPath }: { currentPath: string }) {
const { toggleSidebar } = useSidebar();
return (
{/* Logo */}
{/* Nav */}
{NAV_ITEMS.map(({ to, icon: Icon, label }) => {
const isActive =
to === '/'
? currentPath === '/'
: currentPath.startsWith(to);
return (
{label}
);
})}
{/* Collapse toggle — spec: useSidebar() + custom trigger */}
Collapse
);
}