fix: prevent tab maximize while renaming (#3192)

This commit is contained in:
Carlos Florêncio
2026-08-31 19:37:58 +00:00
committed by GitHub
parent 1ef5dfce6b
commit 87d5b4f172
6 changed files with 316 additions and 2 deletions
@@ -40,6 +40,7 @@ export function TabRenameInput({
className="flex h-full items-center gap-1 px-2"
// Stop the click from selecting the tab while we type.
onClick={(e) => e.stopPropagation()}
onDoubleClick={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
>
{seqBadge != null && (
@@ -0,0 +1,66 @@
import { test, expect } from "../../fixtures/test-base";
import { SessionPage } from "../../pages/session-page";
test.describe("Session tab rename", () => {
// @covers AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.1 through .3
test("keeps rename-input double-clicks out of the maximize handler", async ({
testPage,
apiClient,
seedData,
}) => {
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Agent Tab Rename Double-click",
seedData.agentProfileId,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
if (!task.session_id) throw new Error("createTaskWithAgent did not return a session_id");
await testPage.goto(`/t/${task.id}`);
const session = new SessionPage(testPage);
await session.waitForLoad();
await session.waitForChatIdle({ timeout: 30_000 });
const tab = session.sessionTabBySessionId(task.session_id);
await expect(tab).toBeVisible();
const header = testPage.locator(
`.dv-tabs-and-actions-container:has([data-testid="session-tab-${task.session_id}"])`,
);
const maximizeButton = header.getByTestId("dockview-maximize-btn");
await expect(maximizeButton.locator(".tabler-icon-arrows-maximize")).toBeVisible();
await tab.click({ button: "right" });
await session.contextMenuItem("Rename").click();
const input = testPage.getByTestId("session-tab-rename-input");
await input.click();
await expect(input).toBeFocused();
await input.fill("implementation");
await input.dblclick();
await expect(maximizeButton.locator(".tabler-icon-arrows-maximize")).toBeVisible();
const selection = await input.evaluate((element: HTMLInputElement) => ({
start: element.selectionStart,
end: element.selectionEnd,
length: element.value.length,
}));
expect(selection).toEqual({ start: 0, end: 14, length: 14 });
await testPage.keyboard.press("Escape");
await expect(input).not.toBeVisible();
await tab.dblclick();
await expect(maximizeButton.locator(".tabler-icon-arrows-minimize")).toBeVisible();
await tab.click({ button: "right" });
await session.contextMenuItem("Rename").click();
await input.click();
await expect(input).toBeFocused();
await input.fill("implementation");
await input.dblclick();
await expect(maximizeButton.locator(".tabler-icon-arrows-minimize")).toBeVisible();
await testPage.keyboard.press("Escape");
});
});
@@ -0,0 +1,95 @@
---
created: 2026-08-31
status: done
requirements:
- REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002
system_design:
- ../../specs/ui/system-design/task-agent-tab-reconciliation.md
legacy_specs: []
---
# Implementation Plan: Isolate Agent Tab Rename Double-clicks
## Overview
Keep text-selection double-clicks inside the shared tab rename editor so they
cannot reach the surrounding Agent-tab maximize handler. One work order adds a
browser regression first, applies the shared event-boundary correction, and
runs the focused frontend checks.
## Scope
### In scope
- Preserve native double-click text selection in an active Agent-tab rename
input.
- Prevent that double-click from maximizing or restoring the Dockview group.
- Preserve tab-level double-click maximize behavior outside rename mode.
- Apply the isolation through the shared task tab rename editor.
### Out of scope
- Session-name persistence, validation, commit, cancel, or error behavior.
- Dockview maximize state management or layout persistence.
- Phone and tablet session-control composition.
- Quick Chat tab rename behavior, which uses a different editor.
## Confirmed root cause
`SessionTab` mounts `TabRenameInput` inside a `ContextMenuTrigger` whose
`onDoubleClick` calls `useTabMaximizeOnDoubleClick`. The editor stops bubbling
`mousedown` and `click`, but browsers emit a separate bubbling `dblclick` event.
That event reaches the parent maximize handler, which prevents the default text
selection and toggles the Dockview group.
## Technical approach
- Add a focused Chromium Playwright scenario in
`apps/web/e2e/tests/session/session-tab-rename.spec.ts`. Enter Agent-tab rename
mode from the context menu, double-click the input, assert native selection,
and assert that the group remains unmaximized.
- Update `TabRenameInput` in
`apps/web/components/task/tab-rename-input.tsx` to stop propagation of the
shared editor's `dblclick` event without calling `preventDefault`.
- Leave `SessionTab` and `useTabMaximizeOnDoubleClick` unchanged so ordinary
tab-surface double-clicks retain their current maximize-or-restore behavior.
## Tests
- `AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.2`: the Playwright regression
verifies selected input text and unchanged maximize state after an editor
double-click.
- `AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.3`: the same scenario verifies the
existing tab-surface maximize path remains available outside the editor.
## E2E tests
- Chromium:
`apps/web/e2e/tests/session/session-tab-rename.spec.ts` covers the affected
fine-pointer Dockview workflow.
- No mobile E2E change is required because phone and tablet task surfaces do
not mount desktop Dockview Agent tabs or their maximize gesture.
## Work orders
- [x] [Task 01: Isolate Rename Input Double-clicks](task-01-isolate-rename-input-double-clicks.md)
## Verification results
Completed on 2026-08-31.
- The Chromium regression failed before the fix because the rename-input
double-click removed the group's maximize icon by maximizing the group.
- The rebuilt production E2E bundle passed the focused scenario after the
shared editor stopped the bubbling `dblclick` event.
- Web typecheck, focused ESLint, and `git diff --check` passed.
- No mobile test changed because phone and tablet do not mount the affected
Dockview Agent-tab surface.
## Risks
- Calling `preventDefault` at the editor boundary would fix maximize while also
breaking the text-selection behavior being protected. The correction must
stop propagation only.
- Testing only the two individual click events would miss the separately
dispatched `dblclick` that causes the regression.
@@ -0,0 +1,101 @@
---
id: "01-isolate-rename-input-double-clicks"
title: "Isolate Rename Input Double-clicks"
status: done
wave: 1
depends_on: []
plan: "plan.md"
requirements:
- REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002
acceptance_criteria:
- AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.1
- AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.2
- AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.3
system_design:
- ../../specs/ui/system-design/task-agent-tab-reconciliation.md
---
# Task 01: Isolate Rename Input Double-clicks
## Summary
Add a failing desktop browser regression for the Agent-tab rename interaction,
then make the shared task tab rename editor contain double-clicks without
disabling native input selection. Preserve the existing maximize behavior for
double-clicks outside rename mode.
## In scope
- Add the focused Agent-tab rename Playwright regression.
- Stop bubbling `dblclick` events at `TabRenameInput`.
- Verify native selection and unchanged Dockview maximize state.
## Out of scope
- Rename persistence and backend session APIs.
- Dockview layout or maximize-state refactors.
- Quick Chat rename behavior.
- Phone and tablet UI changes.
## Acceptance
- The new Playwright scenario fails on the current code because an editor
double-click maximizes the Agent-tab group.
- Double-clicking the active rename input selects text without changing the
Dockview group's maximize state.
- Double-clicking the non-editing Agent-tab surface still toggles maximize.
## Verification
```bash
pnpm e2e:run tests/session/session-tab-rename.spec.ts
pnpm run typecheck
pnpm exec eslint components/task/tab-rename-input.tsx e2e/tests/session/session-tab-rename.spec.ts
git diff --check
```
Run the first three commands from `apps/web`. Run `git diff --check` from the
repository root.
## Files likely touched
- `apps/web/e2e/tests/session/session-tab-rename.spec.ts`
- `apps/web/components/task/tab-rename-input.tsx`
## Dependencies
None.
## Risks
- Preventing the default `dblclick` action would suppress native input text
selection.
- A selector that observes a different Dockview group could allow the browser
regression to pass while the Agent group still toggles.
## Parallelism
`sequential`
## Inputs
- `REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002`
- `AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.1` through `.3`
- `docs/specs/ui/system-design/task-agent-tab-reconciliation.md`
- `apps/web/components/task/session-tab.tsx`
- `apps/web/components/task/tab-rename-input.tsx`
- `apps/web/components/task/use-tab-maximize.ts`
## Results
Completed on 2026-08-31.
- RED: `pnpm e2e:run --no-build tests/session/session-tab-rename.spec.ts`
failed on the expected maximize-state assertion after an editor
double-click.
- GREEN: `pnpm e2e:run tests/session/session-tab-rename.spec.ts` rebuilt the
production frontend and passed 1 Chromium test.
- `pnpm run typecheck` passed.
- `pnpm exec eslint components/task/tab-rename-input.tsx e2e/tests/session/session-tab-rename.spec.ts`
passed.
- `git diff --check` passed.
@@ -43,13 +43,36 @@ task workbench becomes usable.
shall continue to project the same task session membership through their
existing session controls without mounting desktop workbench tabs.
### REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002: Agent Tab Rename Isolation
**Intent:** Keep inline Agent-tab name editing independent from the desktop
workbench commands attached to the surrounding tab.
#### Acceptance criteria
- **AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.1:** When a fine-pointer user
chooses **Rename** for an Agent tab, the tab shall show a focused inline input
with its current name selected.
- **AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.2:** While the inline rename input
is active, double-clicking its text shall preserve native text selection and
shall not maximize or restore the surrounding Dockview group.
- **AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.3:** Outside rename mode,
double-clicking an eligible desktop workbench tab shall retain the existing
maximize-or-restore behavior.
- **AC-UI-TASK-AGENT-TAB-RECONCILIATION-002.4:** Phone and tablet session
controls shall retain their existing rename and navigation behavior without
exposing desktop Dockview maximize gestures.
## Out of scope
- Changing session creation, lifecycle, ordering, or backend APIs.
- Changing saved desktop layout geometry or the active-panel rules for valid
non-Agent panels.
- Changing session-name persistence or the rename commit, cancel, and failure
behavior.
- Redesigning phone or tablet task navigation and session controls.
## Implementation plan
- [Command-center task focus repair](../../../plans/command-center-task-focus/plan.md)
- [Agent tab rename double-click isolation](../../../plans/agent-tab-rename-double-click/plan.md)
@@ -3,6 +3,7 @@ status: current
system: ui
requirements:
- REQ-UI-TASK-AGENT-TAB-RECONCILIATION-001
- REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002
---
# Task Agent Tab Reconciliation System Design
@@ -19,6 +20,7 @@ the desktop workbench.
| Requirement | Design section |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `REQ-UI-TASK-AGENT-TAB-RECONCILIATION-001` | [Components and responsibilities](#components-and-responsibilities), [Control flow](#control-flow), [Responsive behavior](#responsive-behavior) |
| `REQ-UI-TASK-AGENT-TAB-RECONCILIATION-002` | [Inline rename event boundary](#inline-rename-event-boundary), [Responsive behavior](#responsive-behavior), [Verification design](#verification-design) |
## Components and responsibilities
@@ -34,6 +36,27 @@ the desktop workbench.
- `runAutoSessionTabEffect` reads the current application state, removes stale
Agent panels, ensures the active session panel, and adds current sibling
session panels without activating them.
- `SessionTab` owns the fine-pointer Agent-tab context menu and attaches the
shared Dockview maximize handler to the tab surface.
- `TabRenameInput` owns the inline editor's pointer and keyboard event boundary.
It is shared with task terminal-tab rename mode.
- `useTabMaximizeOnDoubleClick` owns maximize-or-restore behavior outside an
active inline editor.
## Inline rename event boundary
`SessionTab` renders `TabRenameInput` inside the same `ContextMenuTrigger` that
receives tab-level double-clicks. Browsers dispatch `dblclick` as a separate
bubbling event after the individual click events. Stopping only `mousedown` and
`click` therefore does not isolate the editor from the tab-level maximize
handler.
The shared rename editor stops propagation of `mousedown`, `click`, and
`dblclick`. Its `dblclick` boundary does not prevent the default browser action,
so native input text selection remains available. The parent tab maximize
handler remains unchanged and continues to own double-clicks that originate
outside the editor. This boundary also protects the shared task terminal rename
editor without changing terminal naming behavior.
## Data and contracts
@@ -69,7 +92,8 @@ the effect reads the latest session list.
Desktop uses Dockview Agent tabs. Phone and tablet layouts do not mount the
desktop Dockview workbench. Their existing session controls continue to read
the same application-store membership. No mobile composition or touch target
changes.
changes. Inline rename event isolation applies only where the desktop Dockview
tab and editor are mounted.
## Verification design
@@ -77,4 +101,8 @@ A React hook regression test hydrates a multi-session task while the Dockview
API is null. The test publishes the API later and verifies reconciliation.
Existing pure reconciliation tests continue to cover active-tab and sibling
behavior. A Playwright scenario opens a multi-session task from Cmd+K and
verifies that every Agent tab appears without a reload.
verifies that every Agent tab appears without a reload. A focused desktop
Playwright regression enters Agent-tab rename mode, double-clicks the input,
and verifies that native text selection remains active while the Dockview group
stays unmaximized. Mobile coverage is unchanged because phone and tablet do not
mount the affected Dockview tab surface.