theo-agent-dashboard

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

BranchIndicator.tsx (2227B)


      1 import { useState, useRef, useEffect, useCallback } from "react";
      2 
      3 export interface Branch {
      4   session_id: string;
      5   parent_session_id: string;
      6   fork_message_index: number;
      7 }
      8 
      9 interface BranchIndicatorProps {
     10   branches: Branch[];
     11   currentSessionId: string;
     12   onSwitchBranch?: (sessionId: string) => void;
     13 }
     14 
     15 function branchCountText(count: number): string {
     16   return count === 1 ? "1 branch" : `${count} branches`;
     17 }
     18 
     19 export function BranchIndicator({
     20   branches,
     21   currentSessionId,
     22   onSwitchBranch,
     23 }: BranchIndicatorProps) {
     24   const [open, setOpen] = useState(false);
     25   const ref = useRef<HTMLDivElement>(null);
     26 
     27   const handleClickOutside = useCallback((e: MouseEvent) => {
     28     if (ref.current && !ref.current.contains(e.target as Node)) {
     29       setOpen(false);
     30     }
     31   }, []);
     32 
     33   useEffect(() => {
     34     document.addEventListener("mousedown", handleClickOutside);
     35     return () => document.removeEventListener("mousedown", handleClickOutside);
     36   }, [handleClickOutside]);
     37 
     38   if (branches.length === 0) return null;
     39 
     40   return (
     41     <div ref={ref} className="relative inline-block">
     42       <button
     43         type="button"
     44         onClick={() => setOpen(!open)}
     45         className="text-xs text-blue-400 hover:text-blue-300 transition-colors"
     46       >
     47         ⑂ {branchCountText(branches.length)}
     48       </button>
     49 
     50       {open && (
     51         <div className="absolute left-0 top-full z-10 mt-1 w-48 rounded-lg border border-gray-700 bg-gray-900 shadow-lg">
     52           {branches.map((branch) => (
     53             <button
     54               key={branch.session_id}
     55               type="button"
     56               onClick={() => {
     57                 onSwitchBranch?.(branch.session_id);
     58                 setOpen(false);
     59               }}
     60               className={`block w-full px-3 py-2 text-left text-xs transition-colors ${
     61                 branch.session_id === currentSessionId
     62                   ? "bg-blue-600/20 text-blue-300"
     63                   : "text-gray-300 hover:bg-gray-800"
     64               }`}
     65             >
     66               {branch.session_id}
     67               <span className="ml-1 text-gray-500">
     68                 (msg {branch.fork_message_index})
     69               </span>
     70             </button>
     71           ))}
     72         </div>
     73       )}
     74     </div>
     75   );
     76 }