Refine toolbar chat controls

This commit is contained in:
murashit 2026-06-04 22:47:34 +09:00
parent bec6d07e68
commit 46f185689e
5 changed files with 21 additions and 11 deletions

View file

@ -39,13 +39,6 @@ function Toolbar({ model, actions }: { model: ToolbarViewModel; actions: Toolbar
<>
<div className="nav-header codex-panel__toolbar-primary">
<div className="nav-buttons-container codex-panel__toolbar-buttons">
<ToolbarIconButton
icon="message-square-plus"
label="Start new chat"
className="codex-panel__new-chat"
disabled={model.newChatDisabled}
onClick={actions.startNewThread}
/>
<ToolbarIconButton
icon="history"
label={model.historyOpen ? "Hide thread list" : "Show thread list"}
@ -53,6 +46,13 @@ function Toolbar({ model, actions }: { model: ToolbarViewModel; actions: Toolbar
aria-pressed={model.historyOpen ? "true" : "false"}
onClick={actions.toggleHistory}
/>
<ToolbarIconButton
icon="messages-square"
label="Start new chat"
className="codex-panel__new-chat"
disabled={model.newChatDisabled}
onClick={actions.startNewThread}
/>
<RuntimeButtons model={model} actions={actions} />
<StatusButton model={model} actions={actions} />
</div>
@ -86,7 +86,7 @@ function RuntimeButtons({ model, actions }: { model: ToolbarViewModel; actions:
return (
<>
<RuntimeIcon
icon="list-checks"
icon="list-todo"
label="Toggle plan mode"
className="codex-panel__plan-toggle"
active={model.planActive}
@ -101,7 +101,7 @@ function RuntimeButtons({ model, actions }: { model: ToolbarViewModel; actions:
/>
<RuntimeIcon icon="zap" label="Toggle fast mode" active={model.fastActive} onClick={actions.toggleFast} />
<ToolbarIconButton
icon="brain"
icon="bot"
label="Change model and reasoning effort"
className={["codex-panel__runtime-model", model.runtimeOpen ? "is-active" : ""].filter(Boolean).join(" ")}
aria-label="Change model and reasoning effort"

View file

@ -96,7 +96,7 @@ export class CodexThreadsView extends ItemView {
}
override getIcon(): string {
return "list-checks";
return "list-video";
}
override async onOpen(): Promise<void> {

View file

@ -30,8 +30,8 @@ describe("toolbar renderer decisions", () => {
expect(parent.querySelector(".codex-panel__runtime-area")).toBeNull();
expect(parent.querySelector(".codex-panel__runtime-strip")).toBeNull();
expect([...expectPresent(navButtons).children].map((button) => button.getAttribute("aria-label"))).toEqual([
"Start new chat",
"Show thread list",
"Start new chat",
"Toggle plan mode",
"Toggle auto-review",
"Toggle fast mode",
@ -40,6 +40,7 @@ describe("toolbar renderer decisions", () => {
]);
const newChatButton = parent.querySelector<HTMLButtonElement>(".codex-panel__new-chat");
expect(newChatButton?.getAttribute("aria-label")).toBe("Start new chat");
expect(newChatButton?.dataset["icon"]).toBe("messages-square");
expect(newChatButton?.classList.contains("nav-action-button")).toBe(true);
expect(newChatButton?.disabled).toBe(false);
newChatButton?.click();
@ -60,6 +61,7 @@ describe("toolbar renderer decisions", () => {
expect(toggleHistory).toHaveBeenCalled();
const planButton = parent.querySelector<HTMLButtonElement>(".codex-panel__plan-toggle");
expect(planButton?.getAttribute("aria-label")).toBe("Toggle plan mode");
expect(planButton?.dataset["icon"]).toBe("list-todo");
expect(planButton?.getAttribute("aria-pressed")).toBe("false");
expect(planButton?.classList.contains("codex-panel__runtime-icon")).toBe(true);
const autoReviewButton = parent.querySelector<HTMLButtonElement>(".codex-panel__auto-review-toggle");
@ -89,6 +91,7 @@ describe("toolbar renderer decisions", () => {
expect(parent.querySelector(".codex-panel__status-menu-toggle")?.getAttribute("aria-label")).toBe("Hide panel menu");
expect(parent.querySelector(".codex-panel__status-menu-toggle")?.classList.contains("is-active")).toBe(true);
expect(parent.querySelector(".codex-panel__runtime-model")?.getAttribute("aria-label")).toBe("Change model and reasoning effort");
expect(parent.querySelector<HTMLElement>(".codex-panel__runtime-model")?.dataset["icon"]).toBe("bot");
expect(parent.querySelector(".codex-panel__runtime-model")?.classList.contains("is-active")).toBe(true);
expect(parent.querySelector(".codex-panel__runtime-model")?.classList.contains("nav-action-button")).toBe(true);
});

View file

@ -172,6 +172,7 @@ describe("threads view renderer decisions", () => {
const openNewPanel = expectPresent(parent.querySelector<HTMLButtonElement>('[aria-label="Open new panel"]'));
expect(openNewPanel.classList.contains("codex-panel-threads__toolbar-button")).toBe(true);
expect(openNewPanel.classList.contains("codex-panel-threads__row-button")).toBe(false);
expect(openNewPanel.dataset["icon"]).toBe("message-square-plus");
openNewPanel.click();
expect(actions.openNewPanel).toHaveBeenCalledOnce();
const rename = expectPresent(parent.querySelector<HTMLButtonElement>('[aria-label="Rename thread"]'));

View file

@ -78,6 +78,12 @@ describe("CodexThreadsView", () => {
namingMock.generateThreadTitleWithCodex.mockReset();
});
it("uses a distinct thread view icon", async () => {
const view = await threadsView();
expect(view.getIcon()).toBe("list-video");
});
it("renders thread list from app-server history", async () => {
connectionMock.state.client = clientFixture({
listThreads: vi.fn().mockResolvedValue({ data: [threadFixture({ id: "thread", preview: "Thread preview" })] }),