import React, { useEffect, useRef, useState } from 'react'; import { LuCheck, LuChevronDown, LuChevronRight, LuLoader2, } from 'react-icons/lu'; import type { ICopilotStep } from '../../service/copilot/copilot.interface'; import { cn } from './cn'; /** * Collapsible tool/thinking tree for one assistant turn. Each step shows live * state: a spinning loader with a pulsing label while running, then a green * check once done. The tree stays open while Reco works and folds itself to a * one-line summary when the turn completes (the merchant can re-expand it). * * @param props - Component props. * @param props.steps - Steps for this turn, in order. * @return The tree, or null when there are no steps. */ export function CopilotSteps({ steps, }: { steps: ICopilotStep[]; }): React.ReactElement | null { const isWorking: boolean = steps.some(step => step.state === 'running'); const [isExpanded, setIsExpanded] = useState(isWorking); // Tracks the working state across renders so we only auto-collapse on the // moment the turn finishes, never against a manual re-expand afterwards. const wasWorkingRef = useRef(isWorking); useEffect(() => { if (wasWorkingRef.current && !isWorking) setIsExpanded(false); if (!wasWorkingRef.current && isWorking) setIsExpanded(true); wasWorkingRef.current = isWorking; }, [isWorking]); if (steps.length === 0) return null; return (
{isExpanded && (
{/* Connector line with a soft brand fade, instead of a flat border. */} {steps.map(step => (
{step.state === 'running' ? ( ) : ( )}
{step.label} {step.detail && ( {step.detail} )}
))}
)}
); }