diff --git a/frontend/src/components/maps/LocationMapToolbar.jsx b/frontend/src/components/maps/LocationMapToolbar.jsx
index b0390dd..89e48b2 100644
--- a/frontend/src/components/maps/LocationMapToolbar.jsx
+++ b/frontend/src/components/maps/LocationMapToolbar.jsx
@@ -1,5 +1,51 @@
import { MAX_MAP_ZOOM, MIN_MAP_ZOOM, clampMapZoom } from "../../lib/locationMapUtils";
+function ToolbarIcon({ name }) {
+ if (name === "undo") {
+ return (
+
+ );
+ }
+
+ if (name === "redo") {
+ return (
+
+ );
+ }
+
+ if (name === "zoom-in") {
+ return (
+
+ );
+ }
+
+ if (name === "fit") {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
+
export default function LocationMapToolbar({
mode,
editorTool,
@@ -61,19 +107,23 @@ export default function LocationMapToolbar({
>
) : null}
@@ -103,23 +153,34 @@ export default function LocationMapToolbar({
{Math.round(zoom * 100)}%
-
diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css
index bb0add0..8e76f7e 100644
--- a/frontend/src/styles/pages/LocationMapManager.css
+++ b/frontend/src/styles/pages/LocationMapManager.css
@@ -191,6 +191,28 @@
line-height: 1;
}
+.location-map-history-buttons button.location-map-icon-button,
+.location-map-zoom-controls button.location-map-icon-button {
+ width: 40px;
+ min-width: 40px;
+ padding: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.location-map-toolbar-icon {
+ width: 18px;
+ height: 18px;
+ display: block;
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 2.2;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ pointer-events: none;
+}
+
.location-map-tool-buttons button.is-pan.active {
border-color: rgba(245, 158, 11, 0.78);
background: rgba(245, 158, 11, 0.22);
diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts
index b2faa57..c46f712 100644
--- a/frontend/tests/location-map-manager.spec.ts
+++ b/frontend/tests/location-map-manager.spec.ts
@@ -1488,6 +1488,11 @@ test("narrow mobile toolbar keeps map controls tappable without overflow", async
const toolbarButtons = toolbar.getByRole("button");
const buttonCount = await toolbarButtons.count();
expect(buttonCount).toBe(7);
+ await expect(toolbar.getByRole("button", { name: "Undo" })).toBeVisible();
+ await expect(toolbar.getByRole("button", { name: "Redo" })).toBeVisible();
+ await expect(toolbar.getByRole("button", { name: "Zoom out" })).toBeVisible();
+ await expect(toolbar.getByRole("button", { name: "Zoom in" })).toBeVisible();
+ await expect(toolbar.getByRole("button", { name: "Fit" })).toBeVisible();
for (let index = 0; index < buttonCount; index += 1) {
const buttonBox = await toolbarButtons.nth(index).boundingBox();
expect(buttonBox).not.toBeNull();
@@ -1495,6 +1500,17 @@ test("narrow mobile toolbar keeps map controls tappable without overflow", async
expect(buttonBox.width).toBeGreaterThanOrEqual(40);
expect(buttonBox.height).toBeGreaterThanOrEqual(40);
}
+
+ const iconButtons = toolbar.locator(".location-map-icon-button");
+ await expect(iconButtons).toHaveCount(5);
+ for (let index = 0; index < await iconButtons.count(); index += 1) {
+ const iconButtonBox = await iconButtons.nth(index).boundingBox();
+ expect(iconButtonBox).not.toBeNull();
+ if (!iconButtonBox) throw new Error("Toolbar icon button was not measurable");
+ expect(iconButtonBox.width).toBeLessThanOrEqual(44);
+ expect(iconButtonBox.height).toBeLessThanOrEqual(44);
+ await expect(iconButtons.nth(index).locator(".location-map-toolbar-icon")).toHaveCount(1);
+ }
});
test("admin selecting an object does not mark a draft dirty until it changes", async ({ page }) => {