diff --git a/frontend/src/components/session/BranchNode.tsx b/frontend/src/components/session/BranchNode.tsx index cf9a1f9c..5e5ee607 100644 --- a/frontend/src/components/session/BranchNode.tsx +++ b/frontend/src/components/session/BranchNode.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useRef } from 'react' import { CircleDot, CheckCircle2, XCircle, Circle, RotateCcw } from 'lucide-react' import { cn } from '@/lib/utils' import type { BranchResponse } from '@/types/branching' @@ -18,7 +18,7 @@ const STATUS_CONFIG: Record = { icon: CircleDot, textClass: 'text-accent', badgeClass: 'bg-accent-dim text-accent-text', - borderClass: 'border-accent/40', + borderClass: 'border-accent/50', label: 'Active', }, solved: { @@ -60,34 +60,35 @@ 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 showDetail = isActive || isHovered + + const hasDetail = branch.context_summary || branch.status_reason + const showPopover = isHovered && hasDetail && !isActive return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > + {/* Card */} + + {/* Floating popover for HOVERED non-active branches */} + {showPopover && (
-
- {branch.context_summary ? ( - <> - {branch.context_summary.tried.length > 0 && ( -

- Tried:{' '} - {branch.context_summary.tried.join(', ')} -

- )} - {branch.context_summary.concluded && ( -

- Result:{' '} - {branch.context_summary.concluded} -

- )} - - ) : ( -

No activity yet

- )} - {branch.status_reason && ( -

- Reason:{' '} - {branch.status_reason} -

- )} -
- {branch.step_count} step{branch.step_count !== 1 ? 's' : ''} -
+
+ + {branch.label}
+
- + )}
) } + +/** Shared detail content used by both inline (active) and popover (hover) */ +function BranchDetail({ branch }: { branch: BranchResponse }) { + return ( + <> + {branch.context_summary && ( + <> + {branch.context_summary.tried.length > 0 && ( +

+ Tried:{' '} + {branch.context_summary.tried.join(', ')} +

+ )} + {branch.context_summary.concluded && ( +

+ Result:{' '} + {branch.context_summary.concluded} +

+ )} + + )} + {branch.status_reason && ( +

+ Reason:{' '} + {branch.status_reason} +

+ )} +
+ {branch.step_count} step{branch.step_count !== 1 ? 's' : ''} +
+ + ) +}