fix: use toggle buttons for map area flags

This commit is contained in:
Nico 2026-06-04 06:57:00 -07:00
parent 69488bb1ba
commit 214df9faec
3 changed files with 50 additions and 34 deletions

View File

@ -303,24 +303,24 @@ export default function LocationMapBottomSheet({
</select> </select>
</label> </label>
<div className="location-map-object-flags"> <div className="location-map-object-flags">
<label> <button
<input type="button"
type="checkbox" className={selectedObject.visible !== false ? "active" : ""}
checked={selectedObject.visible !== false} aria-pressed={selectedObject.visible !== false}
disabled={saving} disabled={saving}
onChange={(event) => onObjectField("visible", event.target.checked)} onClick={() => onObjectField("visible", selectedObject.visible === false)}
/> >
Visible Visible
</label> </button>
<label> <button
<input type="button"
type="checkbox" className={selectedObject.locked ? "active" : ""}
checked={Boolean(selectedObject.locked)} aria-pressed={Boolean(selectedObject.locked)}
disabled={saving} disabled={saving}
onChange={(event) => onObjectField("locked", event.target.checked)} onClick={() => onObjectField("locked", !selectedObject.locked)}
/> >
Locked Locked
</label> </button>
</div> </div>
<div className="location-map-editor-actions"> <div className="location-map-editor-actions">
<button type="button" onClick={onDuplicateObject} disabled={saving}>Duplicate</button> <button type="button" onClick={onDuplicateObject} disabled={saving}>Duplicate</button>

View File

@ -657,25 +657,29 @@
gap: 0.45rem; gap: 0.45rem;
} }
.location-map-object-flags label { .location-map-object-flags button {
min-height: 40px; min-height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 0.45rem;
padding: 0.35rem 0.5rem; padding: 0.35rem 0.5rem;
border: 1px solid var(--color-border-light); border: 1px solid var(--color-border-light);
border-radius: 999px; border-radius: 999px;
background: rgba(15, 23, 34, 0.58); background: rgba(15, 23, 34, 0.58);
color: #f8fafc; color: #f8fafc;
font-weight: 800; font-weight: 800;
cursor: pointer;
} }
.location-map-object-flags input { .location-map-object-flags button.active {
min-height: 0; border-color: rgba(96, 165, 250, 0.76);
width: 18px; background: rgba(59, 130, 246, 0.32);
height: 18px; box-shadow: inset 0 0 0 1px rgba(96, 165, 250, 0.18);
padding: 0; }
.location-map-object-flags button:disabled {
opacity: 0.55;
cursor: not-allowed;
} }
.location-map-zone-empty { .location-map-zone-empty {

View File

@ -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: "Continue Editing" }).click();
await page.getByRole("button", { name: "Edit Areas" }).click(); await page.getByRole("button", { name: "Edit Areas" }).click();
await page.getByRole("button", { name: "Map area Bakery" }).click(); await page.getByRole("button", { name: "Map area Bakery" }).click();
await expect(page.getByLabel("Visible")).toBeChecked(); const visibleToggle = page.getByRole("button", { name: "Visible" });
await expect(page.getByLabel("Locked")).not.toBeChecked(); 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.getByRole("button", { name: "Map area Bakery" })).toHaveCount(0);
await expect(page.locator(".location-map-sheet-header strong")).toHaveText("Edit Areas"); await expect(page.locator(".location-map-sheet-header strong")).toHaveText("Edit Areas");
await expect(page.getByText("No visible map areas")).toBeVisible(); 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.locator(".location-map-resize-handle")).toBeVisible();
await expect(page.getByRole("spinbutton", { name: "X" })).toHaveCount(0); 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 lockedToggle.click();
await expect(page.getByLabel("Locked")).toBeChecked(); await expect(lockedToggle).toHaveAttribute("aria-pressed", "true");
await expect(page.getByRole("textbox", { name: "Label" })).toBeEnabled(); 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: "X" })).toHaveCount(0);
await expect(page.getByRole("spinbutton", { name: "Y" })).toHaveCount(0); await expect(page.getByRole("spinbutton", { name: "Y" })).toHaveCount(0);
await expect(page.getByRole("spinbutton", { name: "W" })).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 page.keyboard.press("ArrowRight");
await expect(bakeryArea).toHaveAttribute("x", "40"); await expect(bakeryArea).toHaveAttribute("x", "40");
await page.getByLabel("Locked").click(); await lockedToggle.click();
await expect(page.getByLabel("Locked")).not.toBeChecked(); await expect(lockedToggle).toHaveAttribute("aria-pressed", "false");
await expect(page.locator(".location-map-resize-handle")).toBeVisible(); 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: "Continue Editing" }).click();
await page.getByRole("button", { name: "Edit Areas" }).click(); await page.getByRole("button", { name: "Edit Areas" }).click();
await page.locator(".location-map-object", { hasText: "Bakery" }).locator("rect").first().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(page.getByText("No visible map areas")).toBeVisible();
await expect( 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); await expect(page.getByLabel("Height")).toHaveCount(0);
const fieldRows = page.locator(".location-map-field-row"); const fieldRows = page.locator(".location-map-field-row");
await expect(fieldRows).toHaveCount(2); 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 selectedPrimaryActions = page.locator(".location-map-selected-primary-actions");
const selectedSecondaryActions = page.locator(".location-map-selected-secondary-actions"); const selectedSecondaryActions = page.locator(".location-map-selected-secondary-actions");
await expect(selectedPrimaryActions.getByRole("button", { name: "Save Draft" })).toBeVisible(); 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 selectedSecondaryButtonBox = await selectedSecondaryActions.getByRole("button", { name: "Add Area" }).boundingBox();
const labelBox = await labelInput.boundingBox(); const labelBox = await labelInput.boundingBox();
const firstFieldRowBox = await fieldRows.first().boundingBox(); const firstFieldRowBox = await fieldRows.first().boundingBox();
const firstFlagButtonBox = await objectFlagButtons.first().boundingBox();
expect(selectedPrimaryBox).not.toBeNull(); expect(selectedPrimaryBox).not.toBeNull();
expect(selectedSecondaryButtonBox).not.toBeNull(); expect(selectedSecondaryButtonBox).not.toBeNull();
expect(labelBox).not.toBeNull(); expect(labelBox).not.toBeNull();
expect(firstFieldRowBox).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"); throw new Error("Selected object draft actions were not measurable");
} }
expect(selectedPrimaryBox.y).toBeLessThan(labelBox.y); expect(selectedPrimaryBox.y).toBeLessThan(labelBox.y);
expect(selectedSecondaryButtonBox.height).toBeGreaterThanOrEqual(40); expect(selectedSecondaryButtonBox.height).toBeGreaterThanOrEqual(40);
expect(firstFieldRowBox.height).toBeLessThanOrEqual(54); expect(firstFieldRowBox.height).toBeLessThanOrEqual(54);
expect(firstFlagButtonBox.height).toBeGreaterThanOrEqual(40);
await page.getByRole("button", { name: "View" }).click(); await page.getByRole("button", { name: "View" }).click();
await expect(page.getByRole("textbox", { name: "Label" })).toHaveCount(0); await expect(page.getByRole("textbox", { name: "Label" })).toHaveCount(0);
}); });