import { createPortal } from 'react-dom'; import { useRef, useState } from 'react'; import ReactMarkdown from 'react-markdown'; import './CodeChangePlan.css'; import { FaPlus, FaTrash, FaEdit } from 'react-icons/fa'; // Tooltip component const StepDetails = ({ stepItem, position }) => { const style = { position: 'absolute', top: position?.top ?? 0, left: position?.left ?? 0, }; return ( <div className="step-details-popdown" style={style}> <div className="tooltip-action"> {stepItem.action === 'create' && <FaPlus className="create-icon" />} {stepItem.action === 'delete' && <FaTrash className="delete-icon" />} {stepItem.action === 'modify' && <FaEdit className="modify-icon" />} <span> {stepItem.action === 'create' ? 'Create File' : stepItem.action === 'delete' ? 'Delete File' : stepItem.action === 'modify' ? 'Modify File' : stepItem.action} </span> </div> <div className="tooltip-file-path">{stepItem.file_path}</div> </div> ); }; // Main component const CodeChangePlan = ({ steps }) => { const [hoveredStepIndex, setHoveredStepIndex] = useState(null); const [tooltipPosition, setTooltipPosition] = useState(null); const stepRefs = useRef([]); const handleMouseEnter = (index) => { const stepElement = stepRefs.current[index]; if (stepElement) { const rect = stepElement.getBoundingClientRect(); // const tooltipPadding = 10; setTooltipPosition({ top: rect.bottom + window.scrollY + 6, // 6px spacing left: rect.left + window.scrollX, }); } setHoveredStepIndex(index); }; const handleMouseLeave = () => { setHoveredStepIndex(null); setTooltipPosition(null); }; return ( <> <ul className="code-change-plan"> {steps.map((step, index) => ( <li key={index} className="code-change-plan-step" onMouseEnter={() => handleMouseEnter(index)} onMouseLeave={handleMouseLeave} ref={(el) => (stepRefs.current[index] = el)} > <ReactMarkdown>{step.change_instruction}</ReactMarkdown> </li> ))} </ul> {hoveredStepIndex !== null && createPortal( <StepDetails stepItem={steps[hoveredStepIndex]} position={tooltipPosition} />, document.body )} </> ); }; export default CodeChangePlan;