From f46c8071fba4d8e27fcb6c9ae600f252fabee90d Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Sat, 31 Oct 2026 08:59:41 -0500 Subject: [PATCH] fix(ui): make the Coordinator composer footer opaque (#18455) ## Thinking Path > - Paperclip helps people manage AI agents and their work. > - The Coordinator workspace shows a task transcript and a message composer. > - The composer footer can cover part of the transcript on desktop. > - The footer has a transparent background, so text shows through accessory panels and gaps. > - This pull request gives the footer a solid background from the active theme. > - Users can read the composer controls without text from the transcript behind them. ## Linked Issues or Issue Description **What happened?** The Coordinator composer footer lets transcript text show through the area above the message field. **Expected behavior** The full footer has a solid surface in light and dark themes. **Steps to reproduce** 1. Enable the Coordinator workspace. 2. Open a task with enough messages to scroll. 3. Show a composer accessory, such as queued messages or a pending question. 4. Scroll the transcript behind the footer on desktop. **Paperclip version or commit** Base commit: f2db909393de124caf6a5380a52d4e0e1d621661. **Deployment mode** Built from source. The change affects the Coordinator workspace. Related work: https://github.com/paperclipai/paperclip/pull/17983 added the workspace. Searches for an opaque or transparent composer fix found no duplicate. ## What Changed - Use `var(--background)` for the full Coordinator composer footer. - Keep the outer footer square so transcript text cannot show at its corners. - Block clicks through the footer gaps. Forward wheel input from these gaps to the transcript. - Keep editor scrolling, zoom input, and the classic workspace behavior. - Add regression tests for the footer surface, wheel input, and canceled forwarded events. - Keep wheel modifier keys. Use the font size to calculate horizontal distance for line-mode input. - Remove the old comment that describes a transparent footer. ## Verification - Passed: 173 tests in `TaskChatComposerDock`, `TaskChatComposerStyles`, `TaskChatComposer`, `TaskChatQueuedMessages`, and `TaskMessageScroller`. - The surface and wheel tests fail on the previous implementation and pass with this change. - The latest wheel tests reproduce lost modifier keys and excessive horizontal distance on the prior commit. The cancellation test fails when the cancellation guard is removed. - Passed: `pnpm check:token-gates` and `git diff --check`. - Passed: local Chromium checks with the production dock and built UI CSS in light and dark themes at desktop and mobile sizes. The checks cover solid corners, blocked clicks in footer gaps, wheel input, message entry, and horizontal overflow. - The browser fixture reproduces the hidden-control click when the old pointer rules are restored. These are local fixture checks, not a deployed acceptance result. - Passed: `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter @paperclipai/ui build`. - Full local `pnpm -r typecheck` and `pnpm build` could not finish because Cargo is absent from this environment. The full local test run was stopped without a complete result after these missing prerequisites were confirmed. Full CI now passes on the current commit. - Passed: [full CI](https://github.com/paperclipai/paperclip/actions/runs/41205893876) on commit `37feaef28`. Greptile and Paperclip both gave this commit 5/5. Both review threads are resolved. - Paperclip review found hidden clicks through footer gaps and exposed corners. This change addresses both findings. The first CI quality review required a regression test. This change adds those tests. The later review requested a cancellation test and better horizontal wheel handling. This change addresses both items. ## Risks - Low risk. The CSS selector applies only inside the Coordinator workspace. - The footer now captures clicks across its full area. Wheel input in empty footer space still scrolls the transcript. - The dock forwards wheel input to the transcript handler so earlier-history loading still receives that input. - No API, data, or migration changes. ## Model Used - OpenAI Codex, based on GPT-6 (`gpt-6`), with reasoning, tool use, and code execution. The runtime does not expose its context window. The model ID for the original saved CSS patch is not retained in the task evidence. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip --- .../task-chat/TaskChatComposerDock.test.tsx | 117 ++++++++++++++++++ .../task-chat/TaskChatComposerDock.tsx | 28 ++++- .../task-chat/TaskChatComposerStyles.test.ts | 8 ++ ui/src/index.css | 6 +- 4 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 ui/src/components/task-chat/TaskChatComposerDock.test.tsx diff --git a/ui/src/components/task-chat/TaskChatComposerDock.test.tsx b/ui/src/components/task-chat/TaskChatComposerDock.test.tsx new file mode 100644 index 00000000000..68ba2e5623c --- /dev/null +++ b/ui/src/components/task-chat/TaskChatComposerDock.test.tsx @@ -0,0 +1,117 @@ +// @vitest-environment jsdom + +import { flushSync } from "react-dom"; +import { createRoot, type Root } from "react-dom/client"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { TaskChatComposerDock } from "./TaskChatComposerDock"; + +describe("TaskChatComposerDock", () => { + let container: HTMLDivElement; + let root: Root; + + beforeEach(() => { + container = document.createElement("div"); + document.body.appendChild(container); + root = createRoot(container); + }); + + afterEach(() => { + flushSync(() => root.unmount()); + container.remove(); + vi.restoreAllMocks(); + }); + + function render(coordinator = true) { + const onTranscriptWheel = vi.fn(); + flushSync(() => root.render( +
+
+
+ +