diff --git a/e2e/settingsHeaderLayout.spec.ts b/e2e/settingsHeaderLayout.spec.ts new file mode 100644 index 000000000..49d678cb6 --- /dev/null +++ b/e2e/settingsHeaderLayout.spec.ts @@ -0,0 +1,36 @@ +import { expect, test } from "./fixtures"; + +test("dirty settings keep scope labels and navigation inside the page header", async ({ workbench: page }) => { + await page.keyboard.press("Meta+,"); + await expect(page.getByRole("dialog", { name: "Settings", exact: true })).toBeVisible(); + await page.evaluate(async () => { + const path = "/src/features/settings/model/staging.ts"; + const { selectPage, stage } = await import(/* @vite-ignore */ path); + stage("languages.node", "project", "languages.node.interpreter", "/custom/node"); + selectPage("languages.node"); + }); + const scope = page.getByRole("radiogroup", { name: "Settings scope" }); + const reset = page.getByRole("button", { name: "Reset", exact: true }); + await expect(reset).toBeVisible(); + for (const width of [1000, 640, 520]) { + await page.setViewportSize({ width, height: 760 }); + const fits = await scope.evaluate((scope) => { + const header = scope.parentElement!; + const bounds = header.getBoundingClientRect(); + return [...header.querySelectorAll("button")].every((button) => { + const box = button.getBoundingClientRect(); + const range = document.createRange(); + range.selectNodeContents(button); + return ( + box.left >= bounds.left && + box.right <= bounds.right && + [...range.getClientRects()].every((r) => r.top >= box.top - 1 && r.bottom <= box.bottom + 1) + ); + }); + }); + expect(fits).toBe(true); + } + await reset.click(); + await expect(reset).toHaveCount(0); + await expect(scope.getByRole("radio", { name: "This project" })).toBeVisible(); +}); diff --git a/src/features/settings/dialog/SettingsDialog.module.css b/src/features/settings/dialog/SettingsDialog.module.css index f457b4a8d..a385f206e 100644 --- a/src/features/settings/dialog/SettingsDialog.module.css +++ b/src/features/settings/dialog/SettingsDialog.module.css @@ -75,9 +75,10 @@ .pageHeader { flex: none; display: flex; + flex-wrap: wrap; align-items: center; gap: 12px; - height: 40px; + min-height: 40px; padding: 0 12px 0 20px; } .history { @@ -120,6 +121,7 @@ } .scope { display: inline-flex; + flex: none; padding: 2px; border-radius: var(--radius-small); box-shadow: inset 0 0 0 1px var(--border-strong); @@ -130,6 +132,7 @@ border-radius: 3px; color: var(--fg-muted); font-size: var(--fs-small); + white-space: nowrap; } .scopeButton:hover { color: var(--fg-emphasis);