From fb2a99598c43cacdb0e376646057452f550b6609 Mon Sep 17 00:00:00 2001 From: Taylor Ho Date: Mon, 27 Jul 2026 23:10:16 -0700 Subject: [PATCH] fix(composer): lone typing group uses the full row width instead of truncating at the strip cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BotActivityBar.tsx: apply the typing slot's max-w-64 cap only when the group shares the strip with working-agent pills. The cap exists so a long "X, Y, and N more are typing" label can't inflate the strip's scroll extent alongside pills, but it was unconditional — as the strip's LONE item a two-name label ("Alpha Debug and Beta Debug are typing...") got cut off at 256px even with the row mostly empty. The lone item already shrinks with the container (min-w-0 through the slot chain), so it now consumes the row's free width and only ellipsizes when the container is genuinely narrow. - channels.spec.ts: add "lone typing group uses the full row width" e2e regression — three typers push the label past the old cap, then asserts no truncation at full width (scrollWidth <= clientWidth) and graceful ellipsizing without scroll fades at a 200px row. Verified the test fails against the old unconditional cap. Co-authored-by: Taylor Ho Signed-off-by: Taylor Ho --- .../features/channels/ui/BotActivityBar.tsx | 14 ++++-- desktop/tests/e2e/channels.spec.ts | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/desktop/src/features/channels/ui/BotActivityBar.tsx b/desktop/src/features/channels/ui/BotActivityBar.tsx index cf8b9a6e5..7b2ae4ef0 100644 --- a/desktop/src/features/channels/ui/BotActivityBar.tsx +++ b/desktop/src/features/channels/ui/BotActivityBar.tsx @@ -775,10 +775,16 @@ export function BotActivityComposerAction({ {() => (
0 && "max-w-64", // Composer-edge alignment when the typing group leads // the strip (no pills): 0.75rem/1rem composer padding // + 1px border. Mirrors the standalone row's old diff --git a/desktop/tests/e2e/channels.spec.ts b/desktop/tests/e2e/channels.spec.ts index 4dfb14e77..124fe4d9b 100644 --- a/desktop/tests/e2e/channels.spec.ts +++ b/desktop/tests/e2e/channels.spec.ts @@ -3109,6 +3109,52 @@ test("typing indicator shows avatars and maintains stable name order", async ({ ).toContainText("alice and bob are typing"); }); +test("lone typing group uses the full row width instead of truncating at the strip cap", async ({ + page, +}) => { + await page.goto("/"); + + await page.getByTestId("channel-random").click(); + await expect(page.getByTestId("chat-title")).toHaveText("random"); + await waitForMockLiveSubscription(page, "random", KIND_TYPING_INDICATOR); + + // Three typers push the label past the strip's shared-slot cap (max-w-64, + // 256px): with no pills the typing group is the strip's LONE item and must + // consume the row's free width instead of cutting the label off mid-name. + for (const identity of [ + TEST_IDENTITIES.alice, + TEST_IDENTITIES.bob, + TEST_IDENTITIES.charlie, + ]) { + await page.evaluate((pubkey) => { + window.__BUZZ_E2E_EMIT_MOCK_TYPING__?.({ + channelName: "random", + pubkey, + }); + }, identity.pubkey); + } + + const label = page.getByTestId("message-typing-indicator-label"); + await expect(label).toContainText("alice, bob, and charlie are typing"); + + // No truncation with room to spare: the label's content fits its box. + await expect + .poll(() => label.evaluate((el) => el.scrollWidth - el.clientWidth)) + .toBeLessThanOrEqual(0); + + // Genuinely narrow, the lone group still shrinks with the container and + // ellipsizes (rather than overflowing into scroll under an edge fade). + await page + .getByTestId("channel-composer-activity-row") + .evaluate((element) => { + element.style.width = "200px"; + }); + await expect + .poll(() => label.evaluate((el) => el.scrollWidth - el.clientWidth)) + .toBeGreaterThan(0); + await expect(page.getByTestId("bot-activity-strip-fade-end")).toHaveCount(0); +}); + test("sidebar shows unread indicator for newly active channels", async ({ page, }) => {