Show thinking effort as segmented control for short lists

Present the runtime "Thinking effort" field as a single-click segmented
button group when the adapter's option set is small (Claude 4, Cursor 3),
matching the accepted runtime wireframe — all choices visible, one click
(Recognition-over-Recall, Fitts). Adapters with long effort lists
(Codex 6, OpenCode 7) keep the dropdown fallback to avoid overflow.

The segmented group is a keyboard-navigable radiogroup (arrow keys move
selection, roving tabindex). Behavior is covered by render tests for both
the segmented (short-list) and dropdown (long-list) branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
committed 2026-07-22 15:25:46 +00:00
1 parent 0372cccc89
commit ddc1ea554c
2 files changed
+148 -2

No files matched your search

@@ -650,4 +650,54 @@ describe("AgentConfigForm environment selector", () => {
expect(mockAgentsApi.testEnvironment).toHaveBeenCalledTimes(1);
expect(result.container.textContent).toContain("Network unavailable");
});
it("renders thinking effort as a segmented group for adapters with a short effort list", async () => {
const result = await renderForm(
[makeEnvironment({ id: "local-1", name: "Local", driver: "local" })],
{ adapterType: "claude_local" },
);
roots.push(result.root);
const group = result.container.querySelector<HTMLElement>(
'[role="radiogroup"][aria-label="Thinking effort"]',
);
expect(group).toBeTruthy();
const segments = Array.from(group!.querySelectorAll('[role="radio"]'));
expect(segments.map((segment) => segment.textContent?.trim())).toEqual([
"Auto",
"Low",
"Medium",
"High",
]);
// "Auto" (the empty default) is selected when nothing is configured.
expect(segments[0]?.getAttribute("aria-checked")).toBe("true");
await act(async () => {
segments
.find((segment) => segment.textContent?.trim() === "High")
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
await flushReact();
const updatedSegments = Array.from(
result.container.querySelectorAll('[role="radiogroup"][aria-label="Thinking effort"] [role="radio"]'),
);
const highSegment = updatedSegments.find((segment) => segment.textContent?.trim() === "High");
expect(highSegment?.getAttribute("aria-checked")).toBe("true");
expect(updatedSegments[0]?.getAttribute("aria-checked")).toBe("false");
});
it("keeps thinking effort as a dropdown for adapters with a long effort list", async () => {
const result = await renderForm(
[makeEnvironment({ id: "local-1", name: "Local", driver: "local" })],
{ adapterType: "opencode_local" },
);
roots.push(result.root);
expect(
result.container.querySelector('[role="radiogroup"][aria-label="Thinking effort"]'),
).toBeNull();
expect(result.container.textContent).toContain("Thinking effort");
});
});