fix(panel): task-detail tab state in URL, nav placement, kanban overflow, sidebar divider, tooltip sweep

- Task detail: active tab lives in ?tab= (survives reload, back/forward, and
  prev/next task jumps); prev/next arrows move into the header row next to
  Actions instead of their own row above the title
- Constraints section always starts collapsed (project boilerplate)
- Kanban: native overflow scroll replaces Radix ScrollArea (display:table
  viewport let cards grow past the column and clip); columns share width
  (flex-1, 18rem floor, 24rem cap); dark column colors normalized to /40 tints
- Sidebar footer: drop the Separator doubled with the wrapper's border-t
- Tooltips: self-providing Tooltip root (300ms) + hover hints across sidebar,
  header, task detail, kanban, and every icon-only button that had none
This commit is contained in:
Renn F
2026-07-11 10:59:26 +02:00
parent 5a0fce7da4
commit e211a3c15e
37 changed files with 891 additions and 484 deletions
+57 -25
View File
@@ -26,7 +26,11 @@ import {
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useUIStore } from "@/store";
// Flat list, in the exact order product wants the sidebar to read top to
@@ -73,10 +77,9 @@ export function SidebarNav({
<nav className="space-y-1 px-2">
{navItems.map((item) => {
const isActive = pathname.startsWith(item.href);
return (
const link = (
<Link
prefetch={false}
key={item.href}
href={item.href}
onClick={onNavigate}
className={cn(
@@ -86,12 +89,22 @@ export function SidebarNav({
: "text-muted-foreground hover:bg-muted hover:text-foreground",
collapsed && "justify-center px-2",
)}
title={collapsed ? item.title : undefined}
>
<item.icon className="h-5 w-5 shrink-0" />
{!collapsed && <span>{item.title}</span>}
</Link>
);
// Icon-only rail: the label moves into a tooltip.
return collapsed ? (
<Tooltip key={item.href}>
<TooltipTrigger asChild>{link}</TooltipTrigger>
<TooltipContent side="right">{item.title}</TooltipContent>
</Tooltip>
) : (
<span key={item.href} className="block">
{link}
</span>
);
})}
</nav>
);
@@ -105,27 +118,36 @@ export function SidebarFooter({
collapsed?: boolean;
onNavigate?: () => void;
}) {
// No Separator here: both wrappers (desktop aside + mobile Sheet) already
// draw a border-t, and a second line reads as a rendering glitch.
return (
<div className="space-y-2">
<Separator />
<div className="space-y-1">
{footerItems.map((item) => (
<div className="space-y-1">
{footerItems.map((item) => {
const link = (
<Link
prefetch={false}
key={item.href}
href={item.href}
onClick={onNavigate}
className={cn(
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",
collapsed && "justify-center px-2",
)}
title={collapsed ? item.title : undefined}
>
<item.icon className="h-5 w-5" />
{!collapsed && <span>{item.title}</span>}
</Link>
))}
</div>
);
return collapsed ? (
<Tooltip key={item.href}>
<TooltipTrigger asChild>{link}</TooltipTrigger>
<TooltipContent side="right">{item.title}</TooltipContent>
</Tooltip>
) : (
<span key={item.href} className="block">
{link}
</span>
);
})}
</div>
);
}
@@ -162,19 +184,29 @@ export function Sidebar() {
<span className="font-semibold text-lg">RoboCo</span>
</Link>
)}
<Button
variant="ghost"
size="icon"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className={cn(sidebarCollapsed && "mx-auto")}
>
<ChevronLeft
className={cn(
"h-4 w-4 transition-transform",
sidebarCollapsed && "rotate-180",
)}
/>
</Button>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className={cn(sidebarCollapsed && "mx-auto")}
aria-label={
sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"
}
>
<ChevronLeft
className={cn(
"h-4 w-4 transition-transform",
sidebarCollapsed && "rotate-180",
)}
/>
</Button>
</TooltipTrigger>
<TooltipContent side="right">
{sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
</TooltipContent>
</Tooltip>
</div>
{/* Navigation */}