mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-11 05:11:49 +01:00
fix(ui): keep new-task composer stable during submission (#20365)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People use the New task dialog to send work to an agent. > - The dialog uses the shared task composer. > - A send request added an empty header with a bottom margin. > - That margin increased the composer height by 12 pixels. > - This pull request shows the header only when it has content. > - The composer keeps its size and position while the request runs. ## Linked Issues or Issue Description **What happened?** The New task composer grew by 12 pixels when a person sent a task with a description and no separate title. On desktop, the centered dialog moved up by 6 pixels and the editor moved down by 6 pixels. On mobile, the editor moved down by 12 pixels. **Expected behavior** The composer, editor, and dialog must keep their size and position while the task request runs. **Steps to reproduce** 1. Open New task. 2. Enter a task description without a separate title. 3. Send the task while the create request is still pending. 4. Compare the composer and editor bounds before and after the send. **Paperclip version or commit** Reproduced on `0e3fdebea8` in the production NewIssueDialog component through its existing Storybook story. **Deployment mode** Local source checkout. The browser check uses fixture requests and starts no agent runs. No duplicate fix was found in the open PR and issue search. Related open PR #19725 changes keyboard and pinch-zoom sizing; it does not change the empty header during a task send. ## What Changed - Keep the header absent during a normal send when it has no title, subtask context, or notice. - Keep the existing title, subtask context, connection retry notice, and error message. - Extend the submit test to check stable composer sections for description-only tasks, titled tasks, and subtasks. ## Verification - `pnpm exec vitest run ui/src/components/NewIssueDialog.test.tsx ui/src/components/task-chat/TaskChatComposer.test.tsx`: 253 tests passed. - The new description-only regression failed on the original code because an empty header appeared. It passed after the fix. The title and subtask cases passed in both versions. - Chromium browser check at viewport widths 1280 and 390: the original composer grew by 12 pixels. After the fix, all measured bounds for the composer, editor, and dialog stayed equal before and during the send. - `pnpm check:token-gates`: passed. - `git diff --check`: passed. - No documentation change is needed. The task creation contract stays the same. - The worktree preflight installed dependencies but could not build Runner because Cargo is absent. UI verification completed. [CI passed](https://github.com/paperclipai/paperclip/actions/runs/42702272345) for `53aa01c169559da1b31fd224c60ebeabd4ccf9c5`. It covers typecheck, build, general tests, and all eight end-to-end test shards. ## Risks - Low risk. The change only controls an empty header during a normal send. Existing tests cover connection retry and error notices. - No API, database, dependency, or design token changes. ## Model Used - OpenAI GPT-6 (Codex), with reasoning, tool use, and code execution. The session does not expose a more specific backend model ID or context window size. ## 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 <noreply@paperclip.ing>
This commit is contained in:
1 parent
0e3fdebea8
commit
02bfe71a6b
2 files changed
+12
-4
No files matched your search
@@ -1503,22 +1503,30 @@ describe("NewIssueDialog", () => {
|
||||
act(() => root.unmount());
|
||||
});
|
||||
|
||||
it("shows the create-task loading state only in the submit button", async () => {
|
||||
it.each([
|
||||
{ name: "description only", defaults: { description: "Pending task" } },
|
||||
{ name: "explicit title", defaults: { title: "Pending task" } },
|
||||
{ name: "sub-task", defaults: { description: "Pending task", parentId: "parent-1", parentTitle: "Parent task" } },
|
||||
])("keeps the composer layout stable while submitting a task with $name", async ({ defaults }) => {
|
||||
mockIssuesApi.create.mockReturnValue(new Promise(() => undefined));
|
||||
dialogState.newIssueDefaults = { title: "Pending task" };
|
||||
dialogState.newIssueDefaults = defaults;
|
||||
|
||||
const { root } = renderDialog(container);
|
||||
await flush();
|
||||
|
||||
const submitButton = Array.from(container.querySelectorAll("button"))
|
||||
.find((button) => button.getAttribute("aria-label") === "Create task");
|
||||
.find((button) => button.getAttribute("data-testid") === "task-chat-composer-send");
|
||||
expect(submitButton).not.toBeUndefined();
|
||||
const composer = container.querySelector(".paperclip-task-chat-composer")!;
|
||||
const sections = Array.from(composer.children);
|
||||
|
||||
await act(async () => {
|
||||
submitButton!.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
});
|
||||
await flush();
|
||||
|
||||
expect(mockIssuesApi.create).toHaveBeenCalledTimes(1);
|
||||
expect(Array.from(composer.children)).toEqual(sections);
|
||||
expect(submitButton?.querySelector(".animate-spin")).not.toBeNull();
|
||||
expect(submitButton?.getAttribute("aria-busy")).toBe("true");
|
||||
expect(container.textContent).not.toContain("Creating issue");
|
||||
|
||||
@@ -1467,7 +1467,7 @@ function AccountNewIssueDialog({ ignoreDefaults }: { ignoreDefaults: boolean })
|
||||
runSettings: composerSettings,
|
||||
onRunSettingsChange: setComposerSettings,
|
||||
header:
|
||||
hasTitle || isSubIssueMode || durableCreate.pending || resendError ? (
|
||||
hasTitle || isSubIssueMode || (durableCreate.pending && durableCreate.status !== "sending") || resendError ? (
|
||||
<div className="mb-3 flex flex-col gap-2 text-xs">
|
||||
{durableCreate.pending && durableCreate.status !== "sending" ? (
|
||||
<PendingSendNotice
|
||||
|
||||
Reference in new issue
Block a user