fix(ui): keep the tools panel mounted so a tool's expanded detail survives

antd's Collapse kept the panel mounted once opened, so a tool a user had
expanded stayed expanded after closing and reopening Tools. Base UI renders
only the open branch, so the migration silently reset every ToolItem.

The regression test passes against the antd original, fails against the
migration without keepMounted, and passes with it.
This commit is contained in:
Yuneng Jiang 2026-08-13 12:50:56 -07:00
parent b4092f476f
commit dfdafbf89b
No known key found for this signature in database
2 changed files with 21 additions and 6 deletions

View file

@ -2,7 +2,7 @@
* Core tests for Tools section
*/
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, it, expect } from "vitest";
import { parseToolsFromLog } from "./utils";
@ -152,6 +152,8 @@ describe("ToolsSection", () => {
});
});
const isShown = (text: string) => screen.queryAllByText(text).some((el) => el.closest("[hidden]") === null);
describe("ToolsSection rendering", () => {
it("summarises how many tools were provided and called", () => {
render(<ToolsSection log={logWithTools(["get_weather", "search_web"], "get_weather")} />);
@ -175,12 +177,25 @@ describe("ToolsSection rendering", () => {
it("reveals the tool list only after the section is expanded", async () => {
render(<ToolsSection log={logWithTools(["get_weather", "search_web"], "get_weather")} />);
expect(screen.queryByText("called")).not.toBeInTheDocument();
expect(screen.queryByText("not called")).not.toBeInTheDocument();
expect(isShown("called")).toBe(false);
expect(isShown("not called")).toBe(false);
await userEvent.click(screen.getByText("Tools"));
expect(await screen.findByText("called")).toBeInTheDocument();
expect(screen.getByText("not called")).toBeInTheDocument();
await waitFor(() => expect(isShown("called")).toBe(true));
expect(isShown("not called")).toBe(true);
});
it("keeps a tool's expanded detail across a close and reopen", async () => {
render(<ToolsSection log={logWithTools(["get_weather", "search_web"], "get_weather")} />);
await userEvent.click(screen.getByText("Tools"));
await userEvent.click(await screen.findByText(/1\. get_weather/));
expect(isShown("Description")).toBe(true);
await userEvent.click(screen.getByText("Tools"));
await userEvent.click(screen.getByText("Tools"));
await waitFor(() => expect(isShown("Description")).toBe(true));
});
});

View file

@ -52,7 +52,7 @@ export function ToolsSection({ log }: ToolsSectionProps) {
</span>
</div>
</CollapsibleTrigger>
<CollapsibleContent>
<CollapsibleContent keepMounted>
<div className="flex flex-col gap-2 px-4 pb-4">
{tools.map((tool) => (
<ToolItem key={tool.name} tool={tool} />