--- date: 2026-10-17 pr: pending feature: Phase 006 follow-up - Arco class-name cleanup, tooltip content props, tool panel width clamp, Escape dialog fallback impact: Cosmetic styling fix plus one behavior fix. Dead naive-ui CSS class names in the chat components are rewritten to Arco equivalents so the toolbar, model label, drawer body scrolling, and mobile breakpoints receive their intended styles again; Arco tooltips that carried their label as trailing default-slot text now pass it through the content prop so the text stops being rendered into the layout flow; the workspace/terminal panel no longer squeezes the chat column narrow enough to wrap the input toolbar; and Escape again closes Arco chat dialogs because the fallback no longer looks for naive-ui's .n-modal-mask. No chat store logic, no /chat-run payload, and no message rendering path is touched. --- # Phase 006 follow-up: Arco style cleanup and Esc dialog fallback Branch: `phase/006-chat-arco` Touched feature: chat toolbar styling, chat dialogs, session context menu layout, Esc-to-close fallback ## Why Phase 006 migrated the chat page to Arco, but the manual checklist walkthrough surfaced four problems that the automated checks could not see: 1. Opening the workspace/terminal panel squeezed the chat column so far that the input toolbar wrapped "Add attachment" into a vertical stack and truncated the model label. 2. 35 `:deep(.n-*)` rules in the chat components were left behind by the migration. They silently stopped matching because Arco uses different class names, and `grep naive-ui` never sees them because they are class names in a style block rather than an import. 3. `useKeyboard.ts` still looked for `.n-modal-mask` to close dialogs on Escape. Every chat dialog had moved to Arco, so Escape no longer closed the model picker or session search. 4. Four Arco tooltips carried their label as trailing default-slot text (`{{ t(...) }}`). naive-ui rendered the tooltip slot as an overlay so the text was harmless; Arco renders the default slot inline, so those text nodes sat in the flex row as zero-width items and contributed to the toolbar squeeze above. ## What changed - `ChatPanel.vue` — `toolPanelMaxWidth()` now reserves `CHAT_MAIN_MIN_WIDTH` (620px) for the chat column instead of a flat 120px, so the toolbar always has room. `showToolPanel` already re-clamps on open, so persisted widths from older builds are corrected on the next toggle. Dead naive classes rewritten: `.n-button` → `.arco-btn`, and the new-chat drawer's `-content` / `-body-content-wrapper` layers collapsed onto `.arco-drawer` / `.arco-drawer-body` because Arco has no such nesting. - `ChatInput.vue` — dropped the `.n-button__content` / `.n-button__border` / `.n-button__ripple` / `.n-base-wave` rules; Arco's `a-button` is already `display: flex` and carries a transparent border, so `gap` and `border-color` now go on the button itself. `.n-switch` → `.arco-switch`, `.n-button__icon` → `.arco-btn-icon`. The context-length, attach, and model tooltips now pass their label via `:content`. `.input-toolbar` is pinned to `flex-wrap: nowrap`. - `TerminalPanel.vue` — the new-session tooltip passes its label via `:content`. - `MessageList.vue`, `MessageItem.vue`, `SessionSearchModal.vue` — same class-name rewrite; `.n-drawer-body-content-wrapper` → `.arco-drawer-body`, `.n-modal-body-wrapper` → `.arco-modal`, `.n-input` → `.arco-input`. - `useKeyboard.ts` — the Escape fallback now finds the visible `.arco-modal` and clicks its `.arco-modal-close-btn`. ## Verification The toolbar was measured with the workspace panel open across viewport widths 1600 / 1280 / 1100 / 1024 / 900 / 820. `.input-toolbar` stays a single 32px row at every width and `.input-model-label` is no longer clipped (`scrollWidth === clientWidth`). Before the fix the same measurement showed a 90px-tall two-row toolbar and a truncated model label. ## Behavior impact Cosmetic only, plus one fix. Toolbar, model label, drawer body scrolling and mobile breakpoints now actually receive their intended styles. Tooltip labels stop being emitted into the layout. Escape now closes Arco chat dialogs again. No chat store logic, no `/chat-run` payload, and no message rendering path was touched. ## Regression coverage - `tests/client/session-search.test.ts` — asserts Escape clicks an open Arco modal's close button and ignores leftover naive-ui markup. - `tests/e2e/chat-input-dropdown.spec.ts`, `tests/e2e/chat-rendering-smoke.spec.ts` — unchanged, still green (35 e2e tests). ```bash npm run test # 274 files / 2027 tests npm run test:e2e # 35 tests npm run harness:check npm run build ```