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>
</label>
<div className="location-map-object-flags">
<label>
<input
type="checkbox"
checked={selectedObject.visible !== false}
disabled={saving}
onChange={(event) => onObjectField("visible", event.target.checked)}
/>
<button
type="button"
className={selectedObject.visible !== false ? "active" : ""}
aria-pressed={selectedObject.visible !== false}
disabled={saving}
onClick={() => onObjectField("visible", selectedObject.visible === false)}
>
Visible
</label>
<label>
<input
type="checkbox"
checked={Boolean(selectedObject.locked)}
disabled={saving}
onChange={(event) => onObjectField("locked", event.target.checked)}
/>
</button>
<button
type="button"
className={selectedObject.locked ? "active" : ""}
aria-pressed={Boolean(selectedObject.locked)}
disabled={saving}
onClick={() => onObjectField("locked", !selectedObject.locked)}
>
Locked
</label>
</button>
</div>
<div className="location-map-editor-actions">
<button type="button" onClick={onDuplicateObject} disabled={saving}>Duplicate</button>

View File

@ -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 {

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: "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);
});