From f9aa38e57aaae8b1b67dcc13d2175b89e1063a9a Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 4 Jun 2026 06:01:50 -0700 Subject: [PATCH] fix: wrap narrow map toolbar controls --- .../src/styles/pages/LocationMapManager.css | 19 +++-- frontend/tests/location-map-manager.spec.ts | 69 +++++++++++++++++++ 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css index 46fe2bc..0635f01 100644 --- a/frontend/src/styles/pages/LocationMapManager.css +++ b/frontend/src/styles/pages/LocationMapManager.css @@ -938,25 +938,34 @@ @media (max-width: 380px) { .location-map-toolbar { - grid-template-columns: minmax(0, 7.35rem) auto; + grid-template-columns: minmax(0, 1fr) 5rem; } .location-map-toolbar.has-history-slot { - grid-template-columns: minmax(0, 7.35rem) 4.6rem auto; + grid-template-columns: minmax(0, 1fr) 5rem; } .location-map-history-buttons { - width: 4.6rem; + width: 5rem; } .location-map-history-buttons button, .location-map-zoom-controls button { - min-width: 36px; + min-width: 40px; + min-height: 40px; padding: 0.3rem; } + .location-map-zoom-controls, + .location-map-toolbar.has-history-slot .location-map-zoom-controls { + grid-column: 1 / -1; + width: 100%; + justify-self: stretch; + justify-content: space-between; + } + .location-map-zoom-controls span { - min-width: 30px; + min-width: 34px; font-size: 0.78rem; } } diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index afbe2d3..eaa1d8e 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -815,6 +815,75 @@ test("mobile keeps draft preview status compact in the topbar", async ({ page }) expect(editZoomBox.x + editZoomBox.width).toBeLessThanOrEqual(editToolbarBox.x + editToolbarBox.width + 1); }); +test("narrow mobile toolbar keeps map controls tappable without overflow", async ({ page }) => { + await page.setViewportSize({ width: 360, height: 844 }); + await mockMapShell(page); + + const mapState = draftMapState([ + { + id: 1261, + location_map_id: 900, + zone_id: 501, + zone_name: "Bakery", + type: "zone", + label: "Bakery", + x: 40, + y: 40, + width: 260, + height: 160, + rotation: 0, + locked: false, + visible: true, + sort_order: 1, + }, + ], true); + + await page.route("**/households/1/locations/10/map", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify(mapState), + }); + }); + + await page.goto("/stores/100/locations/10/map"); + await page.getByRole("button", { name: "Continue Editing" }).click(); + + const toolbar = page.locator(".location-map-toolbar"); + const modeButtons = page.locator(".location-map-mode-buttons"); + const historyActions = page.locator(".location-map-history-buttons"); + const zoomControls = page.locator(".location-map-zoom-controls"); + const toolbarBox = await toolbar.boundingBox(); + const modeBox = await modeButtons.boundingBox(); + const historyBox = await historyActions.boundingBox(); + const zoomBox = await zoomControls.boundingBox(); + expect(toolbarBox).not.toBeNull(); + expect(modeBox).not.toBeNull(); + expect(historyBox).not.toBeNull(); + expect(zoomBox).not.toBeNull(); + if (!toolbarBox || !modeBox || !historyBox || !zoomBox) { + throw new Error("Narrow mobile toolbar layout was not measurable"); + } + + expect(toolbarBox.x).toBeGreaterThanOrEqual(0); + expect(toolbarBox.x + toolbarBox.width).toBeLessThanOrEqual(361); + expect(modeBox.x + modeBox.width).toBeLessThanOrEqual(historyBox.x); + expect(zoomBox.y).toBeGreaterThan(modeBox.y + modeBox.height - 1); + expect(zoomBox.x).toBeGreaterThanOrEqual(toolbarBox.x); + expect(zoomBox.x + zoomBox.width).toBeLessThanOrEqual(toolbarBox.x + toolbarBox.width + 1); + + const toolbarButtons = toolbar.getByRole("button"); + const buttonCount = await toolbarButtons.count(); + expect(buttonCount).toBe(7); + for (let index = 0; index < buttonCount; index += 1) { + const buttonBox = await toolbarButtons.nth(index).boundingBox(); + expect(buttonBox).not.toBeNull(); + if (!buttonBox) throw new Error("Toolbar button was not measurable"); + expect(buttonBox.width).toBeGreaterThanOrEqual(40); + expect(buttonBox.height).toBeGreaterThanOrEqual(40); + } +}); + test("admin selecting an object does not mark a draft dirty until it changes", async ({ page }) => { await mockMapShell(page);