mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-08 01:57:31 +01:00
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:
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");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user