BrowserResizeTool.tsx

  1import React, { useState } from "react";
  2import { LLMContent } from "../types";
  3
  4interface BrowserResizeToolProps {
  5  toolInput?: unknown; // { width: number, height: number }
  6  isRunning?: boolean;
  7  toolResult?: LLMContent[];
  8  hasError?: boolean;
  9  executionTime?: string;
 10}
 11
 12function BrowserResizeTool({
 13  toolInput,
 14  isRunning,
 15  toolResult,
 16  hasError,
 17  executionTime,
 18}: BrowserResizeToolProps) {
 19  const [isExpanded, setIsExpanded] = useState(false);
 20
 21  // Extract dimensions from toolInput
 22  const width =
 23    typeof toolInput === "object" &&
 24    toolInput !== null &&
 25    "width" in toolInput &&
 26    typeof (toolInput as { width: unknown }).width === "number"
 27      ? (toolInput as { width: number }).width
 28      : 0;
 29
 30  const height =
 31    typeof toolInput === "object" &&
 32    toolInput !== null &&
 33    "height" in toolInput &&
 34    typeof (toolInput as { height: unknown }).height === "number"
 35      ? (toolInput as { height: number }).height
 36      : 0;
 37
 38  // Extract output from toolResult
 39  const output =
 40    toolResult && toolResult.length > 0 && toolResult[0].Text ? toolResult[0].Text : "";
 41
 42  const isComplete = !isRunning && toolResult !== undefined;
 43  const displaySize = width > 0 && height > 0 ? `${width}×${height}` : "...";
 44
 45  return (
 46    <div className="tool" data-testid={isComplete ? "tool-call-completed" : "tool-call-running"}>
 47      <div className="tool-header" onClick={() => setIsExpanded(!isExpanded)}>
 48        <div className="tool-summary">
 49          <span className={`tool-emoji ${isRunning ? "running" : ""}`}>📐</span>
 50          <span className="tool-command">resize {displaySize}</span>
 51          {isComplete && hasError && <span className="tool-error"></span>}
 52          {isComplete && !hasError && <span className="tool-success"></span>}
 53        </div>
 54        <button
 55          className="tool-toggle"
 56          aria-label={isExpanded ? "Collapse" : "Expand"}
 57          aria-expanded={isExpanded}
 58        >
 59          <svg
 60            width="12"
 61            height="12"
 62            viewBox="0 0 12 12"
 63            fill="none"
 64            xmlns="http://www.w3.org/2000/svg"
 65            style={{
 66              transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
 67              transition: "transform 0.2s",
 68            }}
 69          >
 70            <path
 71              d="M4.5 3L7.5 6L4.5 9"
 72              stroke="currentColor"
 73              strokeWidth="1.5"
 74              strokeLinecap="round"
 75              strokeLinejoin="round"
 76            />
 77          </svg>
 78        </button>
 79      </div>
 80
 81      {isExpanded && (
 82        <div className="tool-details">
 83          <div className="tool-section">
 84            <div className="tool-label">Dimensions:</div>
 85            <div className="tool-code">
 86              {width} × {height} pixels
 87            </div>
 88          </div>
 89
 90          {isComplete && output && (
 91            <div className="tool-section">
 92              <div className="tool-label">
 93                Output{hasError ? " (Error)" : ""}:
 94                {executionTime && <span className="tool-time">{executionTime}</span>}
 95              </div>
 96              <pre className={`tool-code ${hasError ? "error" : ""}`}>{output}</pre>
 97            </div>
 98          )}
 99        </div>
100      )}
101    </div>
102  );
103}
104
105export default BrowserResizeTool;