fix(ui): keep console layout usable at mid widths
This commit is contained in:
parent
0c75220adc
commit
8bb5052dd5
6 changed files with 98 additions and 14 deletions
|
|
@ -35,7 +35,7 @@ describe("React app dashboard state view", () => {
|
|||
|
||||
expect(html).toContain('data-ui-theme-toggle="true"');
|
||||
expect(html).toContain('data-ui-theme-current="dark"');
|
||||
expect(html).toContain('aria-label="Switch to light theme"');
|
||||
expect(html).toContain('aria-label="Light theme"');
|
||||
expect(html).toContain('aria-pressed="false"');
|
||||
expect(html).toContain("Theme");
|
||||
expect(html).toContain("Dark");
|
||||
|
|
|
|||
|
|
@ -9,11 +9,10 @@ export interface ThemeToggleProps {
|
|||
|
||||
export function ThemeToggle({ theme, onThemeChange }: ThemeToggleProps) {
|
||||
const nextTheme = getNextUiTheme(theme);
|
||||
const label = `Switch to ${nextTheme} theme`;
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label={label}
|
||||
aria-label="Light theme"
|
||||
aria-pressed={theme === "light"}
|
||||
className="theme-toggle"
|
||||
data-ui-theme-current={theme}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ describe("dashboard UI components", () => {
|
|||
|
||||
expect(body).toContain('class="theme-toggle"');
|
||||
expect(body).toContain('data-ui-theme-current="light"');
|
||||
expect(body).toContain('aria-label="Switch to dark theme"');
|
||||
expect(body).toContain('aria-label="Light theme"');
|
||||
expect(body).toContain('aria-pressed="true"');
|
||||
expect(body).toContain('class="theme-toggle__label"');
|
||||
expect(body).toContain('class="theme-toggle__switch"');
|
||||
|
|
|
|||
|
|
@ -862,13 +862,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width: 780px) {
|
||||
@media (max-width: 1180px), (max-height: 840px) {
|
||||
.dashboard-frame {
|
||||
grid-template-rows: auto auto auto auto;
|
||||
height: auto;
|
||||
min-height: 100vh;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.dashboard-frame__panels {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.dashboard-frame__header {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.dashboard-frame__panels {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.dashboard-frame__panels .service-panel[data-layout="grid"] .panel__body {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 780px) {
|
||||
.dashboard-frame__header,
|
||||
.dashboard-frame__title,
|
||||
.dashboard-header,
|
||||
|
|
|
|||
|
|
@ -109,6 +109,61 @@ test.describe("dashboard page QA gate", () => {
|
|||
expect(metrics.clippedItems).toEqual([]);
|
||||
});
|
||||
|
||||
test("keeps intermediate viewports scrollable without horizontal clipping", async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
test.skip(testInfo.project.name !== "chromium-desktop");
|
||||
|
||||
for (const viewport of [
|
||||
{ width: 900, height: 956 },
|
||||
{ width: 1024, height: 768 },
|
||||
]) {
|
||||
await page.setViewportSize(viewport);
|
||||
await page.goto("/");
|
||||
await waitForDashboardReady(page);
|
||||
|
||||
const metrics = await page.evaluate(() => {
|
||||
const footer = document.querySelector("[data-model-id='footer-status']");
|
||||
const trackedElements = [
|
||||
document.querySelector(".dashboard-frame__header"),
|
||||
...document.querySelectorAll(".telemetry-card"),
|
||||
...document.querySelectorAll(".service-panel"),
|
||||
document.querySelector("[data-model-id='runtime-health']"),
|
||||
footer,
|
||||
].filter((element): element is Element => Boolean(element));
|
||||
|
||||
const footerRect = footer?.getBoundingClientRect();
|
||||
const clippedRight = trackedElements
|
||||
.map((element) => {
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
id: element.getAttribute("data-model-id") || element.className,
|
||||
right: rect.right,
|
||||
width: rect.width,
|
||||
};
|
||||
})
|
||||
.filter((item) => item.right > window.innerWidth + 1 || item.width <= 0);
|
||||
|
||||
return {
|
||||
clippedRight,
|
||||
footerBottomInDocument: (footerRect?.bottom ?? 0) + window.scrollY,
|
||||
frameOverflow: window.getComputedStyle(
|
||||
document.querySelector(".dashboard-frame") as Element,
|
||||
).overflow,
|
||||
scrollHeight: document.documentElement.scrollHeight,
|
||||
scrollWidth: document.documentElement.scrollWidth,
|
||||
};
|
||||
});
|
||||
|
||||
expect(metrics.scrollWidth).toBeLessThanOrEqual(viewport.width);
|
||||
expect(metrics.scrollHeight).toBeGreaterThanOrEqual(
|
||||
Math.ceil(metrics.footerBottomInDocument),
|
||||
);
|
||||
expect(metrics.frameOverflow).not.toBe("hidden");
|
||||
expect(metrics.clippedRight).toEqual([]);
|
||||
}
|
||||
});
|
||||
|
||||
test("renders bookmark rows as a compact divider list", async ({ page }, testInfo) => {
|
||||
test.skip(testInfo.project.name !== "chromium-desktop");
|
||||
|
||||
|
|
@ -210,10 +265,9 @@ test.describe("dashboard page QA gate", () => {
|
|||
|
||||
await expect(page.getByRole("main")).toHaveCount(1);
|
||||
await page.keyboard.press("Tab");
|
||||
const themeToggle = page.getByRole("button", {
|
||||
name: "Switch to light theme",
|
||||
});
|
||||
const themeToggle = page.getByRole("button", { name: "Light theme" });
|
||||
await expect(themeToggle).toBeFocused();
|
||||
await expect(themeToggle).toHaveAttribute("aria-pressed", "false");
|
||||
const themeFocusBoxShadow = await themeToggle.evaluate((element) => {
|
||||
return window.getComputedStyle(element).boxShadow;
|
||||
});
|
||||
|
|
@ -247,8 +301,12 @@ test.describe("dashboard page QA gate", () => {
|
|||
|
||||
await page.goto("/");
|
||||
await waitForDashboardReady(page);
|
||||
await page.getByRole("button", { name: "Switch to light theme" }).click();
|
||||
await page.getByRole("button", { name: "Light theme" }).click();
|
||||
await expect(page.locator("html")).toHaveAttribute("data-ui-theme", "light");
|
||||
await expect(page.getByRole("button", { name: "Light theme" })).toHaveAttribute(
|
||||
"aria-pressed",
|
||||
"true",
|
||||
);
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
expect(results.violations).toEqual([]);
|
||||
|
|
@ -291,15 +349,17 @@ test.describe("dashboard page QA gate", () => {
|
|||
await expect(page.locator("html")).toHaveAttribute("data-ui-theme", "dark");
|
||||
|
||||
const switchToLight = page.getByRole("button", {
|
||||
name: "Switch to light theme",
|
||||
name: "Light theme",
|
||||
});
|
||||
await expect(switchToLight).toBeVisible();
|
||||
await expect(switchToLight).toHaveAttribute("aria-pressed", "false");
|
||||
await switchToLight.click();
|
||||
|
||||
await expect(page.locator("html")).toHaveAttribute("data-ui-theme", "light");
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Switch to dark theme" }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Light theme" })).toHaveAttribute(
|
||||
"aria-pressed",
|
||||
"true",
|
||||
);
|
||||
|
||||
await page.reload();
|
||||
await waitForDashboardReady(page);
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@ test.describe("Storybook theme QA", () => {
|
|||
|
||||
await expect(page.locator("html")).toHaveAttribute("data-ui-theme", "light");
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Switch to dark theme" }),
|
||||
page.getByRole("button", { name: "Light theme" }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Light theme" })).toHaveAttribute(
|
||||
"aria-pressed",
|
||||
"true",
|
||||
);
|
||||
await expect(page.locator("body")).toHaveCSS(
|
||||
"background-color",
|
||||
"rgb(238, 242, 231)",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue