Make the workspace right pane a first-class tab host (#3287)

* feat(app): add persistent workspace side panes

Keep the common review and file-browsing workflow beside the active agent without tearing down pane contents. Workspace tabs now share one compact chip language, assistant file links route into the retained right pane, and diff/file trees share stable geometry.

* fix(app): localize pull request empty state

* test(app): update explorer pane coverage

* fix(app): preserve explorer pane workflows

* test(app): make explorer tab selection idempotent

* fix(app): persist workspace review pins

* fix(app): preserve sidebar scrim drag hook

* fix(app): restore companion pane interactions

* test(app): follow selected sidebar surface
This commit is contained in:
Mohamed Boudra
2026-08-16 18:18:32 +02:00
committed by GitHub
parent 6dcf6a4b08
commit ab274d635e
81 changed files with 2900 additions and 1051 deletions
+7 -11
View File
@@ -2,6 +2,7 @@ import { expect, type Page } from "@playwright/test";
import { buildHostWorkspaceRoute } from "../../../src/utils/host-routes";
import { createTempGitRepo } from "./workspace";
import { getServerId } from "./server-id";
import { createAgentTabFromMenu } from "./workspace-tabs";
// ─── Navigation ────────────────────────────────────────────────────────────
@@ -69,10 +70,10 @@ export async function pressNewTabShortcut(page: Page): Promise<void> {
// ─── Tab bar assertions ───────────────────────────────────────────────────
/** Assert the inline new-agent plus button is visible in the tab bar. */
/** Assert the inline plus button is visible in the tab bar. */
export async function assertNewChatTileVisible(page: Page): Promise<void> {
await expect(
page.getByTestId("workspace-new-agent-tab-inline").filter({ visible: true }).first(),
page.getByTestId("workspace-new-tab-menu-trigger").filter({ visible: true }).first(),
).toBeVisible();
}
@@ -85,14 +86,9 @@ export async function assertNewTabMenuTriggerVisible(page: Page): Promise<void>
// ─── Tab creation actions ─────────────────────────────────────────────────
/** Click the inline plus button to create a draft/chat tab. */
/** Open the new-tab menu and click "New agent" to create a draft/chat tab. */
export async function clickNewChat(page: Page): Promise<void> {
const button = page
.getByTestId("workspace-new-agent-tab-inline")
.filter({ visible: true })
.first();
await expect(button).toBeVisible({ timeout: 10_000 });
await button.click();
await createAgentTabFromMenu(page);
}
/** Open the new-tab menu and click "New terminal". */
@@ -129,9 +125,9 @@ export async function waitForTabWithTitle(
).toBeVisible({ timeout });
}
/** Assert the inline new-agent plus button is visible in the tab bar. */
/** Assert the inline plus button is visible in the tab bar. */
export async function assertSingleNewTabButton(page: Page): Promise<void> {
const buttons = page.getByTestId("workspace-new-agent-tab-inline").filter({ visible: true });
const buttons = page.getByTestId("workspace-new-tab-menu-trigger").filter({ visible: true });
const count = await buttons.count();
expect(count).toBeGreaterThanOrEqual(1);
}