fix: stabilize mobile map toolbar

This commit is contained in:
Nico 2026-06-04 12:45:17 -07:00
parent 8614c0d984
commit e0417783e9
3 changed files with 22 additions and 29 deletions

View File

@ -21,7 +21,7 @@ export default function LocationMapToolbar({
const isAtMinZoom = zoom <= MIN_MAP_ZOOM;
const isAtMaxZoom = zoom >= MAX_MAP_ZOOM;
const showHistorySlot = canManage && hasAnyMap;
const showHistoryControls = mode === "edit" && showHistorySlot;
const canUseHistoryControls = mode === "edit" && showHistorySlot;
return (
<section
@ -56,25 +56,22 @@ export default function LocationMapToolbar({
</div>
{showHistorySlot ? (
<div
className={`location-map-history-buttons ${showHistoryControls ? "" : "is-reserved"}`}
aria-label={showHistoryControls ? "Edit history" : undefined}
aria-hidden={showHistoryControls ? undefined : "true"}
className={`location-map-history-buttons ${canUseHistoryControls ? "" : "is-inactive"}`}
aria-label="Edit history"
>
<button
type="button"
onClick={onUndo}
disabled={!showHistoryControls || saving || history.length === 0}
disabled={!canUseHistoryControls || saving || history.length === 0}
aria-label="Undo"
tabIndex={showHistoryControls ? undefined : -1}
>
<span aria-hidden="true">&#8630;</span>
</button>
<button
type="button"
onClick={onRedo}
disabled={!showHistoryControls || saving || future.length === 0}
disabled={!canUseHistoryControls || saving || future.length === 0}
aria-label="Redo"
tabIndex={showHistoryControls ? undefined : -1}
>
<span aria-hidden="true">&#8631;</span>
</button>

View File

@ -180,11 +180,6 @@
gap: 0.3rem;
}
.location-map-history-buttons.is-reserved {
visibility: hidden;
pointer-events: none;
}
.location-map-history-buttons button {
min-width: 40px;
padding-inline: 0.55rem;
@ -964,7 +959,7 @@
}
.location-map-toolbar {
--location-map-mode-slot: clamp(144px, 37vw, 164px);
--location-map-mode-slot: 148px;
--location-map-history-slot: 80px;
display: grid;
grid-template-columns: var(--location-map-mode-slot) minmax(0, 1fr);
@ -981,14 +976,17 @@
.location-map-mode-group {
grid-column: 1;
width: 100%;
width: var(--location-map-mode-slot);
max-width: var(--location-map-mode-slot);
min-width: 0;
}
.location-map-mode-buttons {
width: 100%;
width: var(--location-map-mode-slot);
max-width: var(--location-map-mode-slot);
min-width: 0;
padding: 0.18rem;
box-sizing: border-box;
}
.location-map-mode-buttons button {
@ -1013,12 +1011,6 @@
justify-self: center;
}
.location-map-history-buttons.is-reserved {
display: flex;
visibility: hidden;
pointer-events: none;
}
.location-map-history-buttons button {
min-width: 40px;
min-height: 40px;

View File

@ -703,7 +703,7 @@ test("admin status follows the visible map when a saved draft exists", async ({
});
test("mobile keeps draft preview status compact in the topbar", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.setViewportSize({ width: 409, height: 838 });
await mockMapShell(page);
const publishedObjects = [
@ -793,10 +793,14 @@ test("mobile keeps draft preview status compact in the topbar", async ({ page })
expect(statusBox.y).toBeLessThan(titleBox.y + titleBox.height);
expect(statusBox.x).toBeGreaterThan(titleBox.x);
expect(toolbarBox.height).toBeLessThanOrEqual(64);
expect(modeBox.width).toBeGreaterThanOrEqual(142);
expect(modeBox.width).toBeLessThanOrEqual(166);
expect(modeBox.width).toBeGreaterThanOrEqual(146);
expect(modeBox.width).toBeLessThanOrEqual(150);
expect(reservedHistoryBox.width).toBeGreaterThanOrEqual(70);
expect(reservedHistoryBox.x).toBeGreaterThan(modeBox.x + modeBox.width - 1);
await expect(historyActions.getByRole("button", { name: "Undo" })).toBeVisible();
await expect(historyActions.getByRole("button", { name: "Redo" })).toBeVisible();
await expect(historyActions.getByRole("button", { name: "Undo" })).toBeDisabled();
await expect(historyActions.getByRole("button", { name: "Redo" })).toBeDisabled();
expect(zoomBox.y).toBeLessThan(modeBox.y + modeBox.height);
expect(zoomBox.x).toBeGreaterThan(reservedHistoryBox.x + reservedHistoryBox.width - 1);
expect(zoomBox.x + zoomBox.width).toBeLessThanOrEqual(toolbarBox.x + toolbarBox.width + 1);
@ -820,8 +824,8 @@ test("mobile keeps draft preview status compact in the topbar", async ({ page })
expect(Math.abs(editModeBox.x - modeBox.x)).toBeLessThanOrEqual(1);
expect(Math.abs(editModeGroupBox.width - modeGroupBox.width)).toBeLessThanOrEqual(1);
expect(Math.abs(editModeBox.width - modeBox.width)).toBeLessThanOrEqual(1);
expect(editModeBox.width).toBeGreaterThanOrEqual(142);
expect(editModeBox.width).toBeLessThanOrEqual(166);
expect(editModeBox.width).toBeGreaterThanOrEqual(146);
expect(editModeBox.width).toBeLessThanOrEqual(150);
expect(Math.abs(editHistoryBox.width - reservedHistoryBox.width)).toBeLessThanOrEqual(1);
expect(editHistoryBox.x).toBeGreaterThan(editModeBox.x + editModeBox.width);
expect(editZoomBox.x).toBeGreaterThan(editHistoryBox.x + editHistoryBox.width);
@ -880,8 +884,8 @@ test("narrow mobile toolbar keeps map controls tappable without overflow", async
expect(toolbarBox.x).toBeGreaterThanOrEqual(0);
expect(toolbarBox.x + toolbarBox.width).toBeLessThanOrEqual(361);
expect(modeBox.width).toBeGreaterThanOrEqual(142);
expect(modeBox.width).toBeLessThanOrEqual(166);
expect(modeBox.width).toBeGreaterThanOrEqual(146);
expect(modeBox.width).toBeLessThanOrEqual(150);
expect(modeBox.x + modeBox.width).toBeLessThanOrEqual(historyBox.x);
expect(zoomBox.y).toBeGreaterThan(modeBox.y + modeBox.height - 1);
expect(zoomBox.x).toBeGreaterThanOrEqual(toolbarBox.x);