From 9745773cb98e0b108dd3819f9e24995185387098 Mon Sep 17 00:00:00 2001 From: Yiru Dong <78648778+moyi-dong@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:19:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E4=BF=AE=E5=A4=8D=E4=B8=AD?= =?UTF-8?q?=E7=AD=89=E5=AE=BD=E5=BA=A6=E4=B8=8B=E8=81=8A=E5=A4=A9=E6=A0=8F?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E9=87=8D=E5=8F=A0=20(#151)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yaowei Zheng --- .../2026-08-03-chat-toolbar-layout.md | 3 +++ changelog/unreleased/README.md | 2 ++ packages/web/e2e/chat.spec.mjs | 21 +++++++++++++++++++ packages/web/src/features/chat/chat-page.tsx | 14 +++++++------ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 changelog/unreleased/2026-08-03-chat-toolbar-layout.md diff --git a/changelog/unreleased/2026-08-03-chat-toolbar-layout.md b/changelog/unreleased/2026-08-03-chat-toolbar-layout.md new file mode 100644 index 0000000..0eff8a7 --- /dev/null +++ b/changelog/unreleased/2026-08-03-chat-toolbar-layout.md @@ -0,0 +1,3 @@ +# Chat toolbar actions stay clear of live statistics + +At medium desktop widths, the pinned sidebar leaves the chat toolbar substantially narrower than the viewport breakpoint suggests. The Agents panel and Workspace actions now remain icon-only until the large-screen breakpoint, preserving space between the running indicator and the live Token, cost, and elapsed-time statistics; their labels return on wider screens, while titles and accessible names keep the compact buttons identifiable. A browser regression test reproduces the approximately 2:1 viewport from issue #150 and verifies that the running status and Token total never intersect. diff --git a/changelog/unreleased/README.md b/changelog/unreleased/README.md index f1ebe53..789b233 100644 --- a/changelog/unreleased/README.md +++ b/changelog/unreleased/README.md @@ -1,5 +1,7 @@ # Unreleased +- [2026-08-03] Web App: medium-width chat toolbars keep the running indicator and live statistics separate by collapsing the Agents panel and Workspace actions to accessible icon-only buttons until the large-screen breakpoint. ([details](2026-08-03-chat-toolbar-layout.md)) + - [2026-08-06] Desktop app: penguin brand icons on every platform, task-completion system notifications (renderer-only, desktop sessions), explicit single-user mode (user/member management rejected with `desktop_single_user` and hidden), and a bundled `penguin` CLI on PATH (automatic on deb; menu-driven install elsewhere, no system Node needed). ([details](2026-08-06-desktop-app.md)) - [2026-08-06] Admin "use system HTTP proxy" switch: server-wide proxy control (default on, live toggle, loopback exemption), off-state proxy-env stripping for agent subprocesses, OS-proxy injection on desktop. ([details](2026-08-06-system-proxy-switch.md)) diff --git a/packages/web/e2e/chat.spec.mjs b/packages/web/e2e/chat.spec.mjs index afcfc9f..3635a63 100644 --- a/packages/web/e2e/chat.spec.mjs +++ b/packages/web/e2e/chat.spec.mjs @@ -67,6 +67,27 @@ test("chat + tool approval + stats/cost/copy + traces + files", async ({ page }) const headerElapsed = page.locator('div.hidden span[title="用时"]'); const elapsedBefore = await headerElapsed.textContent(); await expect(headerElapsed).not.toHaveText(elapsedBefore); + + // Issue #150: at an approximately 2:1 browser size the pinned sidebar leaves the chat + // toolbar much narrower than the viewport breakpoint suggests. The running label used to + // stay expanded and the shrinkable stats row then painted its Token chip over that label. + // Keep the status dot and the live stats, but their rendered boxes must remain disjoint. + await page.setViewportSize({ width: 877, height: 438 }); + await page.waitForTimeout(200); + const runningStatus = page.locator('span[title="运行中"]').filter({ hasText: "运行中" }).first(); + const tokenTotal = page.locator('span[title="Token 累计(Token)"]'); + const [runningBox, tokenBox] = await Promise.all([ + runningStatus.boundingBox(), + tokenTotal.boundingBox(), + ]); + expect(runningBox, "running status is rendered @877").not.toBeNull(); + expect(tokenBox, "Token total is rendered @877").not.toBeNull(); + const overlap = + Math.min(runningBox.x + runningBox.width, tokenBox.x + tokenBox.width) - + Math.max(runningBox.x, tokenBox.x); + expect(overlap, "running status and Token total do not overlap @877").toBeLessThanOrEqual(0); + await page.setViewportSize({ width: 1280, height: 720 }); + await page.waitForTimeout(200); // The user takes control of the running work group (toggle = userToggled), keeps it open, and // opens the exec_command card to watch the arguments. Both must survive the end of the turn. // diff --git a/packages/web/src/features/chat/chat-page.tsx b/packages/web/src/features/chat/chat-page.tsx index 1cb4dd1..2c22e4b 100644 --- a/packages/web/src/features/chat/chat-page.tsx +++ b/packages/web/src/features/chat/chat-page.tsx @@ -1103,9 +1103,10 @@ export function ChatPage() { - {/* Below sm the button is icon-only (title/aria keep the name), same rule as the - workspace button next to it: the label ate the title's room on phones. */} - {S.chat.openAgents} + {/* At md widths the pinned sidebar leaves less room than the viewport breakpoint + suggests. Keep both panel actions icon-only until lg so the running status and + live stats retain their own layout space. */} + {S.chat.openAgents} {/* A pending approval inside a subagent: amber dot (the chip in the stream carries the accessible announcement). */} {anySubagentPending && ( @@ -1136,9 +1137,10 @@ export function ChatPage() { > - {/* Below sm the button is icon-only (title/aria keep the name): the label plus the - running indicator squeezed the session title to nothing on phones. */} - {S.chat.openWorkspace} + {/* Below lg the button is icon-only (title/aria keep the name): between md and lg + the pinned sidebar makes the chat toolbar substantially narrower than the + viewport, so the action labels would squeeze the status into the Token stats. */} + {S.chat.openWorkspace} {/* Conversation index fallback: exactly when the gutter tick rail can't show