fix(desktop): keep sidebar surfaces inset beside relay rail

Apply the multi-community overlap only to the pinned header so footer action cards and draggable channel rows retain their normal sidebar inset. Add a smoke regression for the update card, channel row, and drag overlay.

Signed-off-by: Codex <noreply@openai.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
Codex
2026-08-26 13:14:14 +10:00
committed by Matt Toohey
parent 0affe527e8
commit 321cd750d2
4 changed files with 117 additions and 4 deletions

View File

@@ -85,6 +85,7 @@ export default defineConfig({
"**/relay-connectivity.spec.ts",
"**/unread-pill.spec.ts",
"**/sidebar-more-unread-overlap.spec.ts",
"**/sidebar-community-rail-insets.spec.ts",
"**/sidebar-snapshot.spec.ts",
"**/home-collapsed-top-chrome.spec.ts",
"**/top-chrome-zoom-clearance.spec.ts",

View File

@@ -503,13 +503,12 @@ export function AppSidebar({
variant="sidebar"
>
<div
className={`relative flex min-h-0 flex-1 flex-col overflow-hidden ${
communities.length > 1 ? "md:-ml-[11px] md:w-[calc(100%+11px)]" : ""
}`}
className="relative flex min-h-0 flex-1 flex-col overflow-hidden"
data-sidebar-background
data-testid="app-sidebar-scroll-anchor"
>
<AppSidebarPinnedHeader
className={communities.length > 1 ? "md:-ml-2" : undefined}
channelLabels={dmChannelLabels}
currentPubkey={currentPubkey}
currentChannelId={

View File

@@ -4,6 +4,7 @@ import { TopbarSearch } from "@/features/search/ui/TopbarSearch";
import { SidebarProjectsSection } from "@/features/sidebar/ui/SidebarProjectsSection";
import { FeatureGate } from "@/shared/features";
import type { Channel, SearchHit } from "@/shared/api/types";
import { cn } from "@/shared/lib/cn";
import {
SidebarHeader,
SidebarMenu,
@@ -24,6 +25,7 @@ type SidebarSelectedView =
type AppSidebarPinnedHeaderProps = {
channelLabels: Record<string, string>;
className?: string;
currentChannelId?: string | null;
currentPubkey?: string;
onBrowseChannels?: () => void;
@@ -51,6 +53,7 @@ type AppSidebarPrimaryMenuProps = {
export function AppSidebarPinnedHeader({
channelLabels,
className,
currentChannelId,
currentPubkey,
onBrowseChannels,
@@ -66,7 +69,7 @@ export function AppSidebarPinnedHeader({
}: AppSidebarPinnedHeaderProps) {
return (
<div
className="mx-[3px] shrink-0 px-2 pb-2 pt-3"
className={cn("mx-[3px] shrink-0 px-2 pb-2 pt-3", className)}
data-testid="sidebar-pinned-header"
>
<TopbarSearch

View File

@@ -0,0 +1,110 @@
import { expect, test, type Locator, type Page } from "@playwright/test";
import { installMockBridge } from "../helpers/bridge";
const COMMUNITIES = [
{
id: "ws-a",
name: "Alpha",
relayUrl: "ws://localhost:3000",
addedAt: "2026-01-01T00:00:00.000Z",
},
{
id: "ws-b",
name: "Bravo",
relayUrl: "ws://localhost:3001",
addedAt: "2026-01-02T00:00:00.000Z",
},
];
async function seedCommunities(page: Page) {
await page.addInitScript((communities) => {
window.localStorage.setItem(
"buzz-communities",
JSON.stringify(communities),
);
window.localStorage.setItem("buzz-active-community-id", "ws-a");
}, COMMUNITIES);
}
async function showUpdateCard(page: Page) {
await page.evaluate(() => {
const testWindow = window as Window & {
__BUZZ_E2E__?: { mock?: { updateAvailable?: boolean } };
};
testWindow.__BUZZ_E2E__ = {
...(testWindow.__BUZZ_E2E__ ?? {}),
mock: {
...(testWindow.__BUZZ_E2E__?.mock ?? {}),
updateAvailable: true,
},
};
});
await page.getByTestId("sidebar-profile-card").click();
await page.getByTestId("profile-popover-settings").click();
await page.getByTestId("settings-nav-updates").click();
await page.getByRole("button", { name: "Check for Updates" }).click();
await expect(page.getByTestId("settings-panel-updates")).toContainText(
"Update downloaded. Click to apply.",
);
await page.getByTestId("settings-back-to-app").click();
}
async function settleElementAnimations(locator: Locator) {
await locator.evaluate((element) =>
Promise.allSettled(
element.getAnimations().map((animation) => animation.finished),
),
);
}
test("keeps sidebar cards and drag surfaces inset beside the community rail", async ({
page,
}) => {
await installMockBridge(page, undefined, { skipCommunitySeed: true });
await seedCommunities(page);
await page.goto("/");
await expect(page.getByTestId("community-rail")).toBeVisible();
await showUpdateCard(page);
const sidebar = page.getByTestId("app-sidebar");
const updateCard = page.getByTestId("sidebar-update-card");
await expect(updateCard).toBeVisible();
await settleElementAnimations(updateCard);
const [sidebarBox, updateCardBox] = await Promise.all([
sidebar.boundingBox(),
updateCard.boundingBox(),
]);
expect(sidebarBox).not.toBeNull();
expect(updateCardBox).not.toBeNull();
expect((updateCardBox?.x ?? 0) - (sidebarBox?.x ?? 0)).toBeCloseTo(8, 0);
const channelRow = page.getByTestId("channel-general");
await expect(channelRow).toBeVisible();
const channelRowBox = await channelRow.boundingBox();
expect(channelRowBox).not.toBeNull();
expect((channelRowBox?.x ?? 0) - (sidebarBox?.x ?? 0)).toBeCloseTo(11, 0);
if (!channelRowBox) return;
await page.mouse.move(
channelRowBox.x + channelRowBox.width / 2,
channelRowBox.y + channelRowBox.height / 2,
);
await page.mouse.down();
await page.mouse.move(
channelRowBox.x + channelRowBox.width / 2,
channelRowBox.y + channelRowBox.height / 2 + 8,
{ steps: 5 },
);
const dragOverlay = page.getByTestId("sidebar-channel-drag-overlay");
await expect(dragOverlay).toBeVisible();
const dragOverlayBox = await dragOverlay.boundingBox();
expect(dragOverlayBox).not.toBeNull();
expect(
(dragOverlayBox?.x ?? 0) - (sidebarBox?.x ?? 0),
).toBeGreaterThanOrEqual(10);
await page.mouse.up();
});