From 73101d2d7fbe5d288c54b1c1f1be5b4c4bd646ef Mon Sep 17 00:00:00 2001 From: Wes Date: Sun, 16 Aug 2026 10:11:38 -0600 Subject: [PATCH] fix(desktop): avoid overlapping channel selection paint The sidebar updates active ownership immediately during deferred navigation, but its shared background transition visually retained the old active row while fading in the new one. Exclude background and text colors from channel-row transitions so selection changes atomically, and pin both singular ownership and transition behavior at the pre-route paint boundary. Co-authored-by: Carl Signed-off-by: Wes --- .../features/sidebar/ui/SidebarSection.tsx | 5 +++- desktop/tests/e2e/messaging.spec.ts | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/desktop/src/features/sidebar/ui/SidebarSection.tsx b/desktop/src/features/sidebar/ui/SidebarSection.tsx index 1a6403fb2..5fe1aa315 100644 --- a/desktop/src/features/sidebar/ui/SidebarSection.tsx +++ b/desktop/src/features/sidebar/ui/SidebarSection.tsx @@ -302,7 +302,10 @@ export function ChannelMenuButton({ const button = ( { - const observed = { selectedBeforeRoute: false }; + const observed = { + selectedBeforeRoute: false, + singularSelection: false, + activeBackgroundTransitions: true, + }; Object.assign(window, { __BUZZ_SIDEBAR_SELECTION_OBSERVED__: observed }); const observer = new MutationObserver(() => { + const general = document.querySelector('[data-testid="channel-general"]'); const random = document.querySelector('[data-testid="channel-random"]'); if (random?.getAttribute("data-active") !== "true") return; observer.disconnect(); @@ -2799,6 +2804,19 @@ test("sidebar selection paints before cached channel work starts", async ({ requestAnimationFrame(() => { const title = document.querySelector('[data-testid="chat-title"]'); observed.selectedBeforeRoute = title?.textContent === "general"; + observed.singularSelection = + general?.getAttribute("data-active") === "false" && + document.querySelectorAll( + '[data-testid^="channel-"][data-active="true"]', + ).length === 1; + observed.activeBackgroundTransitions = [general, random].some( + (element) => + element instanceof HTMLElement && + getComputedStyle(element) + .transitionProperty.split(",") + .map((property) => property.trim()) + .includes("background-color"), + ); }); }); }); @@ -2819,12 +2837,18 @@ test("sidebar selection paints before cached channel work starts", async ({ window as Window & { __BUZZ_SIDEBAR_SELECTION_OBSERVED__?: { selectedBeforeRoute: boolean; + singularSelection: boolean; + activeBackgroundTransitions: boolean; }; } - ).__BUZZ_SIDEBAR_SELECTION_OBSERVED__?.selectedBeforeRoute ?? false, + ).__BUZZ_SIDEBAR_SELECTION_OBSERVED__ ?? null, ), ) - .toBe(true); + .toEqual({ + selectedBeforeRoute: true, + singularSelection: true, + activeBackgroundTransitions: false, + }); await expect(page.getByTestId("chat-title")).toHaveText("random"); });