mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Unify sidebar chrome across themes (#2380)
This commit is contained in:
@@ -1,57 +1,4 @@
|
||||
@layer components {
|
||||
[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"],
|
||||
[data-testid="app-sidebar"] [data-sidebar="footer"] {
|
||||
--buzz-sidebar-edge-fade-size: 0.5rem;
|
||||
--buzz-sidebar-edge-fade-surface: hsl(var(--sidebar-background));
|
||||
--buzz-sidebar-edge-fade-transparent: hsl(var(--sidebar-background) / 0);
|
||||
|
||||
background: var(--buzz-sidebar-edge-fade-surface);
|
||||
box-shadow: none;
|
||||
isolation: isolate;
|
||||
position: relative;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"]::before,
|
||||
[data-testid="app-sidebar"] [data-sidebar="footer"]::before {
|
||||
box-shadow: none;
|
||||
content: "";
|
||||
filter: none;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"] > *,
|
||||
[data-testid="app-sidebar"] [data-sidebar="footer"] > * {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"]::before {
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
var(--buzz-sidebar-edge-fade-surface) 0%,
|
||||
var(--buzz-sidebar-edge-fade-transparent) 100%
|
||||
);
|
||||
bottom: calc(var(--buzz-sidebar-edge-fade-size) * -1);
|
||||
height: var(--buzz-sidebar-edge-fade-size);
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
[data-testid="app-sidebar"] [data-sidebar="footer"]::before {
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
var(--buzz-sidebar-edge-fade-surface) 0%,
|
||||
var(--buzz-sidebar-edge-fade-transparent) 100%
|
||||
);
|
||||
height: var(--buzz-sidebar-edge-fade-size);
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: calc(var(--buzz-sidebar-edge-fade-size) * -1);
|
||||
}
|
||||
|
||||
.buzz-side-panel-enter {
|
||||
animation: buzz-side-panel-enter 260ms cubic-bezier(0.32, 0.72, 0, 1) both;
|
||||
transform-origin: right center;
|
||||
|
||||
@@ -22,6 +22,14 @@ async function storedSidebarWidth(page: Page) {
|
||||
);
|
||||
}
|
||||
|
||||
async function loadTheme(page: Page, theme: string) {
|
||||
await page.addInitScript((selectedTheme) => {
|
||||
window.localStorage.setItem("buzz-theme", selectedTheme);
|
||||
}, theme);
|
||||
await installMockBridge(page);
|
||||
await page.goto("/");
|
||||
}
|
||||
|
||||
// Regression guard for the "Leave channel" lockup: with two bundled copies of
|
||||
// @radix-ui/react-dismissable-layer, opening a modal AlertDialog from a modal
|
||||
// Radix ContextMenu left `pointer-events: none` stuck on <body> after the
|
||||
@@ -215,124 +223,88 @@ test("channel owner can delete from the context menu", async ({ page }) => {
|
||||
await expect(page.getByTestId("stream-list")).not.toContainText("general");
|
||||
});
|
||||
|
||||
test("fades the pinned sidebar chrome edges outside the Buzz theme", async ({
|
||||
page,
|
||||
}) => {
|
||||
// The Buzz default theme repaints the pinned header/footer with the
|
||||
// sidebar gradient and drops the edge-fade pseudo-elements, so the fade
|
||||
// treatment under test only exists on non-Buzz themes.
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("buzz-theme", "github-light");
|
||||
});
|
||||
await page.goto("/");
|
||||
for (const theme of ["buzz", "github-light", "catppuccin-mocha"]) {
|
||||
test(`uses the continuous sidebar surface in ${theme}`, async ({ page }) => {
|
||||
await loadTheme(page, theme);
|
||||
|
||||
const pinnedHeader = page.getByTestId("sidebar-pinned-header");
|
||||
const footer = page.locator(
|
||||
'[data-testid="app-sidebar"] [data-sidebar="footer"]',
|
||||
);
|
||||
const channelContent = page.getByTestId("sidebar-channel-content");
|
||||
await expect(pinnedHeader).toBeVisible();
|
||||
await expect(footer).toBeVisible();
|
||||
await expect(channelContent).toBeVisible();
|
||||
|
||||
const fadeStyles = await page.evaluate(() => {
|
||||
const header = document.querySelector<HTMLElement>(
|
||||
'[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"]',
|
||||
);
|
||||
const footerElement = document.querySelector<HTMLElement>(
|
||||
const pinnedHeader = page.getByTestId("sidebar-pinned-header");
|
||||
const footer = page.locator(
|
||||
'[data-testid="app-sidebar"] [data-sidebar="footer"]',
|
||||
);
|
||||
const channelElement = document.querySelector<HTMLElement>(
|
||||
'[data-testid="sidebar-channel-content"]',
|
||||
);
|
||||
const channelContent = page.getByTestId("sidebar-channel-content");
|
||||
await expect(pinnedHeader).toBeVisible();
|
||||
await expect(footer).toBeVisible();
|
||||
await expect(channelContent).toBeVisible();
|
||||
|
||||
if (!header || !footerElement || !channelElement) {
|
||||
throw new Error("Expected sidebar chrome elements to be rendered");
|
||||
}
|
||||
const chromeStyles = await page.evaluate(() => {
|
||||
const header = document.querySelector<HTMLElement>(
|
||||
'[data-testid="app-sidebar"] [data-testid="sidebar-pinned-header"]',
|
||||
);
|
||||
const footerElement = document.querySelector<HTMLElement>(
|
||||
'[data-testid="app-sidebar"] [data-sidebar="footer"]',
|
||||
);
|
||||
const channelElement = document.querySelector<HTMLElement>(
|
||||
'[data-testid="sidebar-channel-content"]',
|
||||
);
|
||||
|
||||
const headerBefore = getComputedStyle(header, "::before");
|
||||
const headerStyle = getComputedStyle(header);
|
||||
const sidebarElement = header.closest<HTMLElement>(
|
||||
'[data-sidebar="sidebar"]',
|
||||
);
|
||||
const sidebarStyle = sidebarElement
|
||||
? getComputedStyle(sidebarElement)
|
||||
: null;
|
||||
const footerStyle = getComputedStyle(footerElement);
|
||||
const footerBefore = getComputedStyle(footerElement, "::before");
|
||||
const channelBefore = getComputedStyle(channelElement, "::before");
|
||||
const channelAfter = getComputedStyle(channelElement, "::after");
|
||||
const headerRect = header.getBoundingClientRect();
|
||||
const footerRect = footerElement.getBoundingClientRect();
|
||||
if (!header || !footerElement || !channelElement) {
|
||||
throw new Error("Expected sidebar chrome elements to be rendered");
|
||||
}
|
||||
|
||||
return {
|
||||
channelAfterBackground: channelAfter.backgroundImage,
|
||||
channelBeforeBackground: channelBefore.backgroundImage,
|
||||
footerBackgroundColor: footerStyle.backgroundColor,
|
||||
footerBackdropFilter: footerBefore.backdropFilter,
|
||||
footerBackground: footerBefore.backgroundImage,
|
||||
footerBoxShadow: footerStyle.boxShadow,
|
||||
footerFadeBoxShadow: footerBefore.boxShadow,
|
||||
footerFadeHeight: Number.parseFloat(footerBefore.height),
|
||||
footerHeight: footerRect.height,
|
||||
footerPointerEvents: footerBefore.pointerEvents,
|
||||
footerPosition: footerBefore.position,
|
||||
footerTopPx: Number.parseFloat(footerBefore.top),
|
||||
footerZIndex: footerBefore.zIndex,
|
||||
headerBackground: headerBefore.backgroundImage,
|
||||
headerBackdropFilter: headerBefore.backdropFilter,
|
||||
headerBackgroundColor: headerStyle.backgroundColor,
|
||||
headerBottomPx: Number.parseFloat(headerBefore.bottom),
|
||||
headerBoxShadow: headerStyle.boxShadow,
|
||||
headerFadeBoxShadow: headerBefore.boxShadow,
|
||||
headerFadeHeight: Number.parseFloat(headerBefore.height),
|
||||
headerHeight: headerRect.height,
|
||||
headerPointerEvents: headerBefore.pointerEvents,
|
||||
headerPosition: headerBefore.position,
|
||||
headerZIndex: headerBefore.zIndex,
|
||||
sidebarBackgroundColor: sidebarStyle?.backgroundColor ?? null,
|
||||
};
|
||||
const headerBefore = getComputedStyle(header, "::before");
|
||||
const headerStyle = getComputedStyle(header);
|
||||
const footerStyle = getComputedStyle(footerElement);
|
||||
const footerBefore = getComputedStyle(footerElement, "::before");
|
||||
const channelBefore = getComputedStyle(channelElement, "::before");
|
||||
const channelAfter = getComputedStyle(channelElement, "::after");
|
||||
|
||||
return {
|
||||
channelAfterBackground: channelAfter.backgroundImage,
|
||||
channelBeforeBackground: channelBefore.backgroundImage,
|
||||
footerBackground: footerStyle.backgroundImage,
|
||||
footerBackgroundColor: footerStyle.backgroundColor,
|
||||
footerBeforeBackground: footerBefore.backgroundImage,
|
||||
footerBeforeContent: footerBefore.content,
|
||||
footerBoxShadow: footerStyle.boxShadow,
|
||||
footerIsolation: footerStyle.isolation,
|
||||
footerMarginTop: Number.parseFloat(footerStyle.marginTop),
|
||||
footerZIndex: footerStyle.zIndex,
|
||||
headerBackground: headerStyle.backgroundImage,
|
||||
headerBackgroundColor: headerStyle.backgroundColor,
|
||||
headerBeforeBackground: headerBefore.backgroundImage,
|
||||
headerBeforeContent: headerBefore.content,
|
||||
headerBoxShadow: headerStyle.boxShadow,
|
||||
headerIsolation: headerStyle.isolation,
|
||||
headerMarginBottom: Number.parseFloat(headerStyle.marginBottom),
|
||||
headerZIndex: headerStyle.zIndex,
|
||||
};
|
||||
});
|
||||
|
||||
expect(chromeStyles.headerBackground).toBe("none");
|
||||
expect(chromeStyles.headerBackgroundColor).toBe("rgba(0, 0, 0, 0)");
|
||||
expect(chromeStyles.headerBeforeBackground).toBe("none");
|
||||
expect(chromeStyles.headerBeforeContent).toBe("none");
|
||||
expect(chromeStyles.headerBoxShadow).toBe("none");
|
||||
expect(chromeStyles.headerIsolation).toBe("auto");
|
||||
expect(chromeStyles.headerMarginBottom).toBe(0);
|
||||
expect(chromeStyles.headerZIndex).toBe("auto");
|
||||
expect(chromeStyles.footerBackground).toBe("none");
|
||||
expect(chromeStyles.footerBackgroundColor).toBe("rgba(0, 0, 0, 0)");
|
||||
expect(chromeStyles.footerBeforeBackground).toBe("none");
|
||||
expect(chromeStyles.footerBeforeContent).toBe("none");
|
||||
expect(chromeStyles.footerBoxShadow).toBe("none");
|
||||
expect(chromeStyles.footerIsolation).toBe("auto");
|
||||
expect(chromeStyles.footerMarginTop).toBe(0);
|
||||
expect(chromeStyles.footerZIndex).toBe("auto");
|
||||
expect(chromeStyles.channelBeforeBackground).toBe("none");
|
||||
expect(chromeStyles.channelAfterBackground).toBe("none");
|
||||
});
|
||||
|
||||
expect(fadeStyles.headerBackground).toContain("gradient");
|
||||
expect(fadeStyles.headerBackgroundColor).toBe(
|
||||
fadeStyles.sidebarBackgroundColor,
|
||||
);
|
||||
expect(fadeStyles.headerBackground).toContain("rgba");
|
||||
expect(fadeStyles.headerBackground).toContain("0) 100%");
|
||||
expect(fadeStyles.headerBackdropFilter).toBe("none");
|
||||
expect(fadeStyles.headerBottomPx).toBeLessThan(0);
|
||||
expect(fadeStyles.headerBoxShadow).toBe("none");
|
||||
expect(fadeStyles.headerFadeBoxShadow).toBe("none");
|
||||
expect(fadeStyles.headerFadeHeight).toBeLessThanOrEqual(10);
|
||||
expect(fadeStyles.headerPointerEvents).toBe("none");
|
||||
expect(fadeStyles.headerPosition).toBe("absolute");
|
||||
expect(fadeStyles.headerZIndex).toBe("5");
|
||||
expect(fadeStyles.footerBackground).toContain("gradient");
|
||||
expect(fadeStyles.footerBackgroundColor).toBe(
|
||||
fadeStyles.sidebarBackgroundColor,
|
||||
);
|
||||
expect(fadeStyles.footerBackground).toContain("rgba");
|
||||
expect(fadeStyles.footerBackground).toContain("0) 100%");
|
||||
expect(fadeStyles.footerBackdropFilter).toBe("none");
|
||||
expect(fadeStyles.footerBoxShadow).toBe("none");
|
||||
expect(fadeStyles.footerFadeBoxShadow).toBe("none");
|
||||
expect(fadeStyles.footerFadeHeight).toBeLessThanOrEqual(10);
|
||||
expect(fadeStyles.footerPointerEvents).toBe("none");
|
||||
expect(fadeStyles.footerPosition).toBe("absolute");
|
||||
expect(fadeStyles.footerTopPx).toBeLessThan(0);
|
||||
expect(fadeStyles.footerZIndex).toBe("5");
|
||||
expect(fadeStyles.channelBeforeBackground).toBe("none");
|
||||
expect(fadeStyles.channelAfterBackground).toBe("none");
|
||||
});
|
||||
}
|
||||
|
||||
test("aligns the sidebar search with the channel title outside the Buzz theme", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("buzz-theme", "github-light");
|
||||
});
|
||||
await page.goto("/");
|
||||
await loadTheme(page, "github-light");
|
||||
await page.getByTestId("channel-general").click();
|
||||
|
||||
const root = page.locator("html");
|
||||
|
||||
Reference in New Issue
Block a user