diff --git a/e2e/compactSettingsControls.spec.ts b/e2e/compactSettingsControls.spec.ts new file mode 100644 index 000000000..11405a241 --- /dev/null +++ b/e2e/compactSettingsControls.spec.ts @@ -0,0 +1,59 @@ +import { expect, test } from "./fixtures"; + +for (const [id, selector] of [ + ["general", "[class*='radios'] label"], + ["notifications", "table tbody td:first-child"], + ["keymap", "[class*='presetLabel']"], + ["editor.inspections", "[class*='profileRow'] > span:first-child"], + ["vcs.issueNavigation", "[class*='pageBody'] button:not([aria-label])"], +]) { + test(`${id} keeps compact labels inside their controls`, async ({ workbench: page }) => { + await page.keyboard.press("Meta+,"); + const dialog = page.getByRole("dialog"); + await expect(dialog).toBeVisible(); + await page.evaluate(async (id) => { + const localePath = "/src/platform/i18n.ts"; + await (await import(/* @vite-ignore */ localePath)).setLocale("zh"); + const stagingPath = "/src/features/settings/model/staging.ts"; + (await import(/* @vite-ignore */ stagingPath)).selectPage(id); + }, id); + const labels = dialog.locator(selector); + await expect(labels.first()).toBeVisible(); + for (const width of [1000, 640, 520]) { + await page.setViewportSize({ width, height: 760 }); + const fits = await labels.evaluateAll((labels) => + labels.every((label) => { + const box = label.getBoundingClientRect(); + const range = document.createRange(); + range.selectNodeContents(label); + const lines = [...range.getClientRects()].filter((r) => r.width > 0 && r.height > 0); + return ( + lines.every((r) => r.left >= box.left - 1 && r.right <= box.right + 1 && r.height <= 24) && + Math.max(...lines.map((r) => r.bottom)) - Math.min(...lines.map((r) => r.top)) <= 24 + ); + }), + ); + expect(fits).toBe(true); + } + }); +} + +for (const [id, selector] of [ + ["general", "[class*='fontRow'] > label"], + ["build.console", "[class*='inlineRow'] > label"], +]) { + test(`${id} keeps a readable width for inline text`, async ({ workbench: page }) => { + await page.keyboard.press("Meta+,"); + await expect(page.getByRole("dialog", { name: "Settings", exact: true })).toBeVisible(); + await page.evaluate(async (id) => { + const localePath = "/src/platform/i18n.ts"; + await (await import(/* @vite-ignore */ localePath)).setLocale("zh"); + const path = "/src/features/settings/model/staging.ts"; + (await import(/* @vite-ignore */ path)).selectPage(id); + }, id); + const text = page.locator(selector).first(); + await expect(text).toBeVisible(); + await page.setViewportSize({ width: 520, height: 760 }); + expect((await text.boundingBox())!.width).toBeGreaterThan(100); + }); +} diff --git a/src/features/settings/keymap/Keymap.module.css b/src/features/settings/keymap/Keymap.module.css index a9f387ed1..919031cc1 100644 --- a/src/features/settings/keymap/Keymap.module.css +++ b/src/features/settings/keymap/Keymap.module.css @@ -12,6 +12,8 @@ margin-bottom: 6px; } .presetLabel { + flex: none; + white-space: nowrap; color: var(--fg); } .presetSelect { diff --git a/src/features/settings/pages/Behavior.module.css b/src/features/settings/pages/Behavior.module.css index c9d19f0f5..5a928ac14 100644 --- a/src/features/settings/pages/Behavior.module.css +++ b/src/features/settings/pages/Behavior.module.css @@ -27,6 +27,7 @@ /* Inline option groups, with custom font controls wrapping together. */ .fontRow { display: flex; + flex-wrap: wrap; align-items: center; gap: 8px; min-height: 28px; @@ -93,11 +94,14 @@ .radios { display: flex; + flex-wrap: wrap; align-items: center; gap: 16px; } .radio { display: inline-flex; + flex: none; + white-space: nowrap; align-items: center; gap: 6px; } @@ -111,6 +115,7 @@ border-collapse: collapse; } .table th { + white-space: nowrap; text-align: left; font-weight: normal; color: var(--fg-muted); @@ -119,6 +124,7 @@ border-bottom: 1px solid var(--border); } .table td { + white-space: nowrap; height: 32px; padding: 0 8px; } diff --git a/src/features/settings/pages/Workflow.module.css b/src/features/settings/pages/Workflow.module.css index 5f004af6e..c634abedd 100644 --- a/src/features/settings/pages/Workflow.module.css +++ b/src/features/settings/pages/Workflow.module.css @@ -25,11 +25,13 @@ /* "[x] Limit history to: [1000] rows" */ .fontFamily { display: flex; + flex-wrap: wrap; align-items: center; gap: 8px; } .inlineRow { display: flex; + flex-wrap: wrap; align-items: center; gap: 8px; min-height: 28px; diff --git a/src/features/settings/pages/editor/Inspections.module.css b/src/features/settings/pages/editor/Inspections.module.css index bcbeefd04..db6a431bc 100644 --- a/src/features/settings/pages/editor/Inspections.module.css +++ b/src/features/settings/pages/editor/Inspections.module.css @@ -14,6 +14,10 @@ .profileSelect { min-width: 220px; } +.profileRow > span { + flex: none; + white-space: nowrap; +} .toolbar { display: flex; align-items: center; diff --git a/src/ui/Button.module.css b/src/ui/Button.module.css index 9d5797cec..5864ea3fb 100644 --- a/src/ui/Button.module.css +++ b/src/ui/Button.module.css @@ -2,6 +2,7 @@ .button { --button-radius: var(--radius-control, 4px); display: inline-flex; + flex-shrink: 0; align-items: center; justify-content: center; gap: 6px;