diff --git a/frontend/src/components/session/BranchNode.tsx b/frontend/src/components/session/BranchNode.tsx index 5e5ee607..dd2aa093 100644 --- a/frontend/src/components/session/BranchNode.tsx +++ b/frontend/src/components/session/BranchNode.tsx @@ -1,4 +1,4 @@ -import { useState, useRef } from 'react' +import { useState } from 'react' import { CircleDot, CheckCircle2, XCircle, Circle, RotateCcw } from 'lucide-react' import { cn } from '@/lib/utils' import type { BranchResponse } from '@/types/branching' @@ -60,22 +60,20 @@ interface BranchNodeProps { export function BranchNode({ branch, depth, isActive, onClick }: BranchNodeProps) { const [isHovered, setIsHovered] = useState(false) - const cardRef = useRef(null) const config = STATUS_CONFIG[branch.status] const Icon = config.icon const hasDetail = branch.context_summary || branch.status_reason - const showPopover = isHovered && hasDetail && !isActive + const showExpanded = isHovered && hasDetail && !isActive return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > - {/* Card */} + {/* Base card — always visible */} - {/* Floating popover for HOVERED non-active branches */} - {showPopover && ( -
-
- - {branch.label} + {/* Expanded card — floats directly on top of the base card */} + {showExpanded && ( + <> + {/* Scrim behind to dim everything */} +
+ + {/* Expanded card positioned over the original */} +
+ +
+ +
- -
+ )}
) } -/** Shared detail content used by both inline (active) and popover (hover) */ +/** Card header row — shared between base and expanded states */ +function CardHeader({ + icon: Icon, + config, + branch, + isActive, +}: { + icon: React.ElementType + config: StatusConfig + branch: BranchResponse + isActive: boolean +}) { + return ( +
+ + + {branch.label} + + + {config.label} + +
+ ) +} + +/** Detail content — shared between inline (active) and expanded (hover) */ function BranchDetail({ branch }: { branch: BranchResponse }) { return ( <>