From 214df9faec86e4a1263f0763ac9fc6f24dc58d05 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 4 Jun 2026 06:57:00 -0700 Subject: [PATCH] fix: use toggle buttons for map area flags --- .../maps/LocationMapBottomSheet.jsx | 32 ++++++++--------- .../src/styles/pages/LocationMapManager.css | 18 ++++++---- frontend/tests/location-map-manager.spec.ts | 34 +++++++++++++------ 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/frontend/src/components/maps/LocationMapBottomSheet.jsx b/frontend/src/components/maps/LocationMapBottomSheet.jsx index f533371..da3897e 100644 --- a/frontend/src/components/maps/LocationMapBottomSheet.jsx +++ b/frontend/src/components/maps/LocationMapBottomSheet.jsx @@ -303,24 +303,24 @@ export default function LocationMapBottomSheet({
-
diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css index 7c8ae10..f5cc450 100644 --- a/frontend/src/styles/pages/LocationMapManager.css +++ b/frontend/src/styles/pages/LocationMapManager.css @@ -657,25 +657,29 @@ gap: 0.45rem; } -.location-map-object-flags label { +.location-map-object-flags button { min-height: 40px; display: flex; align-items: center; justify-content: center; - gap: 0.45rem; padding: 0.35rem 0.5rem; border: 1px solid var(--color-border-light); border-radius: 999px; background: rgba(15, 23, 34, 0.58); color: #f8fafc; font-weight: 800; + cursor: pointer; } -.location-map-object-flags input { - min-height: 0; - width: 18px; - height: 18px; - padding: 0; +.location-map-object-flags button.active { + border-color: rgba(96, 165, 250, 0.76); + background: rgba(59, 130, 246, 0.32); + box-shadow: inset 0 0 0 1px rgba(96, 165, 250, 0.18); +} + +.location-map-object-flags button:disabled { + opacity: 0.55; + cursor: not-allowed; } .location-map-zone-empty { diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index b427394..1aa0fa8 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -993,10 +993,12 @@ test("admin can recover hidden map areas from the empty canvas", async ({ page } await page.getByRole("button", { name: "Continue Editing" }).click(); await page.getByRole("button", { name: "Edit Areas" }).click(); await page.getByRole("button", { name: "Map area Bakery" }).click(); - await expect(page.getByLabel("Visible")).toBeChecked(); - await expect(page.getByLabel("Locked")).not.toBeChecked(); + const visibleToggle = page.getByRole("button", { name: "Visible" }); + const lockedToggle = page.getByRole("button", { name: "Locked" }); + await expect(visibleToggle).toHaveAttribute("aria-pressed", "true"); + await expect(lockedToggle).toHaveAttribute("aria-pressed", "false"); - await page.getByLabel("Visible").click(); + await visibleToggle.click(); await expect(page.getByRole("button", { name: "Map area Bakery" })).toHaveCount(0); await expect(page.locator(".location-map-sheet-header strong")).toHaveText("Edit Areas"); await expect(page.getByText("No visible map areas")).toBeVisible(); @@ -1122,12 +1124,14 @@ test("admin locked map areas hide resize affordances", async ({ page }) => { await expect(page.locator(".location-map-resize-handle")).toBeVisible(); await expect(page.getByRole("spinbutton", { name: "X" })).toHaveCount(0); - await expect(page.getByLabel("Locked")).not.toBeChecked(); + const lockedToggle = page.getByRole("button", { name: "Locked" }); + const visibleToggle = page.getByRole("button", { name: "Visible" }); + await expect(lockedToggle).toHaveAttribute("aria-pressed", "false"); - await page.getByLabel("Locked").click(); - await expect(page.getByLabel("Locked")).toBeChecked(); + await lockedToggle.click(); + await expect(lockedToggle).toHaveAttribute("aria-pressed", "true"); await expect(page.getByRole("textbox", { name: "Label" })).toBeEnabled(); - await expect(page.getByLabel("Visible")).toBeEnabled(); + await expect(visibleToggle).toBeEnabled(); await expect(page.getByRole("spinbutton", { name: "X" })).toHaveCount(0); await expect(page.getByRole("spinbutton", { name: "Y" })).toHaveCount(0); await expect(page.getByRole("spinbutton", { name: "W" })).toHaveCount(0); @@ -1140,8 +1144,8 @@ test("admin locked map areas hide resize affordances", async ({ page }) => { await page.keyboard.press("ArrowRight"); await expect(bakeryArea).toHaveAttribute("x", "40"); - await page.getByLabel("Locked").click(); - await expect(page.getByLabel("Locked")).not.toBeChecked(); + await lockedToggle.click(); + await expect(lockedToggle).toHaveAttribute("aria-pressed", "false"); await expect(page.locator(".location-map-resize-handle")).toBeVisible(); }); @@ -1452,7 +1456,7 @@ test("admin save progress locks empty-canvas recovery actions", async ({ page }) await page.getByRole("button", { name: "Continue Editing" }).click(); await page.getByRole("button", { name: "Edit Areas" }).click(); await page.locator(".location-map-object", { hasText: "Bakery" }).locator("rect").first().click(); - await page.getByLabel("Visible").click(); + await page.getByRole("button", { name: "Visible" }).click(); await expect(page.getByText("No visible map areas")).toBeVisible(); await expect( @@ -2667,6 +2671,11 @@ test("mobile editor uses bottom sheet controls instead of desktop object toolbar await expect(page.getByLabel("Height")).toHaveCount(0); const fieldRows = page.locator(".location-map-field-row"); await expect(fieldRows).toHaveCount(2); + const objectFlagButtons = page.locator(".location-map-object-flags").getByRole("button"); + await expect(objectFlagButtons).toHaveCount(2); + await expect(page.locator(".location-map-object-flags input[type='checkbox']")).toHaveCount(0); + await expect(page.getByRole("button", { name: "Visible" })).toHaveAttribute("aria-pressed", "true"); + await expect(page.getByRole("button", { name: "Locked" })).toHaveAttribute("aria-pressed", "false"); const selectedPrimaryActions = page.locator(".location-map-selected-primary-actions"); const selectedSecondaryActions = page.locator(".location-map-selected-secondary-actions"); await expect(selectedPrimaryActions.getByRole("button", { name: "Save Draft" })).toBeVisible(); @@ -2678,16 +2687,19 @@ test("mobile editor uses bottom sheet controls instead of desktop object toolbar const selectedSecondaryButtonBox = await selectedSecondaryActions.getByRole("button", { name: "Add Area" }).boundingBox(); const labelBox = await labelInput.boundingBox(); const firstFieldRowBox = await fieldRows.first().boundingBox(); + const firstFlagButtonBox = await objectFlagButtons.first().boundingBox(); expect(selectedPrimaryBox).not.toBeNull(); expect(selectedSecondaryButtonBox).not.toBeNull(); expect(labelBox).not.toBeNull(); expect(firstFieldRowBox).not.toBeNull(); - if (!selectedPrimaryBox || !selectedSecondaryButtonBox || !labelBox || !firstFieldRowBox) { + expect(firstFlagButtonBox).not.toBeNull(); + if (!selectedPrimaryBox || !selectedSecondaryButtonBox || !labelBox || !firstFieldRowBox || !firstFlagButtonBox) { throw new Error("Selected object draft actions were not measurable"); } expect(selectedPrimaryBox.y).toBeLessThan(labelBox.y); expect(selectedSecondaryButtonBox.height).toBeGreaterThanOrEqual(40); expect(firstFieldRowBox.height).toBeLessThanOrEqual(54); + expect(firstFlagButtonBox.height).toBeGreaterThanOrEqual(40); await page.getByRole("button", { name: "View" }).click(); await expect(page.getByRole("textbox", { name: "Label" })).toHaveCount(0); });