({ status, approach, technology, keyElements }: PlanCardProps)
| 10 | } |
| 11 | |
| 12 | export function PlanCard({ status, approach, technology, keyElements }: PlanCardProps) { |
| 13 | const detailsRef = useRef<HTMLDetailsElement>(null); |
| 14 | const isRunning = status === "executing" || status === "inProgress"; |
| 15 | |
| 16 | useEffect(() => { |
| 17 | if (!detailsRef.current) return; |
| 18 | detailsRef.current.open = isRunning; |
| 19 | }, [isRunning]); |
| 20 | |
| 21 | const spinner = ( |
| 22 | <span className="inline-block h-3 w-3 rounded-full border-2 border-gray-400 border-t-transparent animate-spin" /> |
| 23 | ); |
| 24 | const checkmark = <span className="text-green-500 text-xs">✓</span>; |
| 25 | |
| 26 | return ( |
| 27 | <div className="my-2 text-sm"> |
| 28 | <details ref={detailsRef} open> |
| 29 | <summary className="flex items-center gap-2 text-gray-600 dark:text-gray-400 cursor-pointer list-none"> |
| 30 | {isRunning ? spinner : checkmark} |
| 31 | <span className="font-medium"> |
| 32 | {isRunning ? "Planning visualization…" : `Plan: ${technology || "visualization"}`} |
| 33 | </span> |
| 34 | <span className="text-[10px]">▼</span> |
| 35 | </summary> |
| 36 | {approach && ( |
| 37 | <div className="pl-5 mt-1.5 space-y-1.5 text-xs text-gray-500 dark:text-zinc-400"> |
| 38 | {technology && ( |
| 39 | <span className="inline-block px-1.5 py-0.5 rounded bg-gray-100 dark:bg-zinc-700 text-gray-600 dark:text-zinc-300 font-medium text-[11px]"> |
| 40 | {technology} |
| 41 | </span> |
| 42 | )} |
| 43 | <p className="text-gray-600 dark:text-gray-400">{approach}</p> |
| 44 | {keyElements && keyElements.length > 0 && ( |
| 45 | <ul className="list-disc pl-4 space-y-0.5"> |
| 46 | {keyElements.map((el, i) => ( |
| 47 | <li key={i}>{el}</li> |
| 48 | ))} |
| 49 | </ul> |
| 50 | )} |
| 51 | </div> |
| 52 | )} |
| 53 | </details> |
| 54 | </div> |
| 55 | ); |
| 56 | } |
nothing calls this directly
no outgoing calls
no test coverage detected