From 872569a5b7365b8fe34399481fbaf242f88b1717 Mon Sep 17 00:00:00 2001 From: baggiiiie Date: Fri, 11 Sep 2026 16:02:26 +0800 Subject: [PATCH] fix(react): prevent long dialog title overflow --- .../connection-remove-confirm.test.ts | 26 ++++++++++++++++--- .../react/src/components/accounts-section.tsx | 3 ++- .../react/src/components/alert-dialog.tsx | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/e2e/scenarios/connection-remove-confirm.test.ts b/e2e/scenarios/connection-remove-confirm.test.ts index b0c8ab8146..736d8740ca 100644 --- a/e2e/scenarios/connection-remove-confirm.test.ts +++ b/e2e/scenarios/connection-remove-confirm.test.ts @@ -41,7 +41,7 @@ scenario( const client = yield* makeClient(api, identity); const slug = IntegrationSlug.make(`rm-confirm-${randomBytes(4).toString("hex")}`); - const name = ConnectionName.make("main"); + const name = ConnectionName.make("longconnectionnamethatmustwrapwithoutoverflow"); yield* Effect.ensuring( Effect.gen(function* () { @@ -73,9 +73,10 @@ scenario( const connections = page.locator("section").filter({ has: page.getByRole("heading", { level: 3, name: "Connections" }), }); - const row = connections.getByText("main", { exact: true }); + const row = connections.getByText(String(name), { exact: true }); const menuTrigger = connections.locator('button[aria-haspopup="menu"]'); const confirm = page.getByRole("alertdialog"); + const removeAction = confirm.getByRole("button", { name: "Remove connection" }); await step("Open the integration's connections", async () => { await visit(page, `/integrations/${slug}`); @@ -85,7 +86,24 @@ scenario( await step("Remove asks for confirmation instead of firing", async () => { await menuTrigger.click(); await page.getByRole("menuitem", { name: "Remove" }).click(); - await confirm.getByText("Remove main?").waitFor(); + const title = confirm.getByText(`Remove ${String(name)}?`); + await title.waitFor(); + await removeAction.getByText("Remove", { exact: true }).waitFor(); + + const layout = await confirm.evaluate((dialog) => { + const title = dialog.querySelector('[data-slot="alert-dialog-title"]'); + if (title === null) return null; + const titleText = document.createRange(); + titleText.selectNodeContents(title); + return { + dialogFits: dialog.scrollWidth <= dialog.clientWidth + 1, + titleWraps: titleText.getClientRects().length > 1, + }; + }); + expect(layout, "the confirmation title wraps without widening the dialog").toEqual({ + dialogFits: true, + titleWraps: true, + }); }); await step("Cancel keeps the connection", async () => { @@ -97,7 +115,7 @@ scenario( await step("Confirming actually removes it", async () => { await menuTrigger.click(); await page.getByRole("menuitem", { name: "Remove" }).click(); - await confirm.getByRole("button", { name: "Remove connection" }).click(); + await removeAction.click(); await confirm.waitFor({ state: "detached" }); await row.waitFor({ state: "detached" }); }); diff --git a/packages/react/src/components/accounts-section.tsx b/packages/react/src/components/accounts-section.tsx index d9189a796f..a87332e654 100644 --- a/packages/react/src/components/accounts-section.tsx +++ b/packages/react/src/components/accounts-section.tsx @@ -571,13 +571,14 @@ function OwnerAccounts(props: { Cancel { if (props.canManageConnections && removingConnection !== null) { void handleRemove(removingConnection); } }} > - Remove connection + Remove diff --git a/packages/react/src/components/alert-dialog.tsx b/packages/react/src/components/alert-dialog.tsx index e26dbfe1d5..8e76c355fa 100644 --- a/packages/react/src/components/alert-dialog.tsx +++ b/packages/react/src/components/alert-dialog.tsx @@ -93,7 +93,7 @@ function AlertDialogTitle({