From 37ea4e1f93a285f34127e1739c46b8df795bcdbd Mon Sep 17 00:00:00 2001 From: German Khokhlov Date: Tue, 3 Nov 2026 20:00:55 +0400 Subject: [PATCH] Keep the six map-source tiles on one row and follow the engine picker in the map tray gate Sentinel-2 made the desktop source row wrap to two rows; the row now lays out every tile in one row (three columns on a phone, as before). scripts/qa-map-source-tray.mjs read the controller's removed imagery internals and counted five tiles between OSM and the styles; it now reads the live base provider and counts the section's tiles and engine picker. The five failures left also fail on origin/main e5d15f24. --- scripts/qa-map-source-tray.mjs | 23 +++++++++++++++++------ src/panelStackLayout.test.mjs | 6 +++--- src/ui/styles/controls.css | 5 ++++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/scripts/qa-map-source-tray.mjs b/scripts/qa-map-source-tray.mjs index 523762742..87a756ed4 100644 --- a/scripts/qa-map-source-tray.mjs +++ b/scripts/qa-map-source-tray.mjs @@ -338,12 +338,16 @@ try { while (!document.body.innerText.includes('Powered by Esri') && performance.now() < creditDeadline) { await new Promise((resolve) => setTimeout(resolve, 25)); } - const provider = controller._activeImageryProvider; + // The base imagery the controller draws now (it is handed to the globe + // engine, src/maps/controller.js). + const liveProvider = () => + controller._liveBaseProvider?.() ?? controller._activeImageryProvider; + const provider = liveProvider(); const before = { activeId: controller.getActiveId(), creditVisible: document.body.innerText.includes('Powered by Esri'), globeShown: styleManager.viewer.scene.globe.show, - hasLayer: Boolean(controller._imageryLayer), + hasLayer: Boolean(liveProvider() ?? controller._imageryLayer), }; provider?.errorEvent?.raiseEvent?.({ timesRetried: 0 }); await new Promise((resolve) => setTimeout(resolve, 50)); @@ -370,7 +374,7 @@ try { lastError: controller.getState().lastError, creditVisible: document.body.innerText.includes('Powered by Esri'), globeShown: styleManager.viewer.scene.globe.show, - hasLayer: Boolean(controller._imageryLayer), + hasLayer: Boolean(liveProvider() ?? controller._imageryLayer), active: [...document.querySelectorAll('.map-stack-chip')] .filter((chip) => chip.getAttribute('aria-pressed') === 'true') .map((chip) => chip.dataset.stackId), @@ -564,9 +568,16 @@ try { await page.keyboard.press('Enter'); await waitTray('true', keyboardSource); - // Visual Styles precede the five Map Source tiles. Keep the existing opening - // handoff to selected OSM, then use the user's real Shift+Tab path into styles. - await pressTabs(5, true); + // Visual Styles precede the Map Source section: its globe-engine picker + // and tiles (OSM is the last). Keep the existing opening handoff to + // selected OSM, then use the user's real Shift+Tab path into styles: one + // press per control of that section. + const mapSourceControls = await page.evaluate( + () => + document.querySelectorAll('.map-stack-chip').length + + (document.getElementById('globe-engine') ? 1 : 0), + ); + await pressTabs(mapSourceControls, true); const noirFocus = await styleFocusMetrics(); check('Shift+Tab reaches Noir with a visible ring while Normal and OSM stay selected', hasVisibleStyleFocus(noirFocus, 'noir') && !noirFocus.selected diff --git a/src/panelStackLayout.test.mjs b/src/panelStackLayout.test.mjs index 5f053e52a..6ffb1979d 100644 --- a/src/panelStackLayout.test.mjs +++ b/src/panelStackLayout.test.mjs @@ -267,7 +267,7 @@ test('expanded left panels integrate their headers with the container shell', () ); }); -test('Map Source uses five compact tiles in the bottom Visual Presets tray', async () => { +test('Map Source keeps its compact tiles on one row in the bottom Visual Presets tray', async () => { const html = await renderApplicationHtml(readFileSync(new URL('../index.html', import.meta.url), 'utf8')); const css = readStylesheet(new URL('../style.css', import.meta.url)); @@ -275,8 +275,8 @@ test('Map Source uses five compact tiles in the bottom Visual Presets tray', asy assert.match(html, /id="control-panel"[\s\S]*?class="map-source-section"[\s\S]*?id="map-stack-chips"/); assert.match( css, - /\.map-stack-chip-row\s*\{[\s\S]*?grid-template-columns:\s*repeat\(5, minmax\(0, 1fr\)\);/, - 'the desktop source selector keeps all five tiles on one row', + /\.map-stack-chip-row\s*\{[\s\S]*?grid-auto-flow:\s*column;\s*grid-auto-columns:\s*minmax\(0, 1fr\);/, + 'the desktop source selector keeps every tile (six with Sentinel-2) on one row', ); }); diff --git a/src/ui/styles/controls.css b/src/ui/styles/controls.css index 812fa3ddd..91115e206 100644 --- a/src/ui/styles/controls.css +++ b/src/ui/styles/controls.css @@ -815,7 +815,9 @@ html:not([lang='en']) .pp-slider-row > .pp-slider-mini-label { .map-stack-chip-row { display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); + /* One row, whatever the number of sources (six with Sentinel-2). */ + grid-auto-flow: column; + grid-auto-columns: minmax(0, 1fr); gap: 4px; } @@ -854,6 +856,7 @@ html:not([lang='en']) .pp-slider-row > .pp-slider-mini-label { @media (max-width: 620px) { .map-stack-chip-row { + grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); } }