feat: toggle map route visibility

This commit is contained in:
2026-06-13 08:02:20 +02:00
parent f3fdf15a3e
commit ab8cad1931

View File

@@ -367,25 +367,43 @@ function htmlPage(): string {
} }
.theme-toggle { .theme-toggle {
position: fixed;
top: 16px;
right: 16px;
z-index: 900;
width: 40px; width: 40px;
height: 40px; height: 40px;
padding: 0; padding: 0;
justify-content: center; justify-content: center;
}
.top-right-controls {
position: fixed;
top: 16px;
right: 16px;
z-index: 900;
display: grid;
gap: 8px;
}
.route-toggle {
width: 40px;
height: 40px;
padding: 0;
justify-content: center;
}
.theme-toggle,
.route-toggle {
background: var(--timeline-surface-soft); background: var(--timeline-surface-soft);
color: var(--timeline-text); color: var(--timeline-text);
border: 1px solid var(--timeline-border); border: 1px solid var(--timeline-border);
box-shadow: var(--shadow-soft); box-shadow: var(--shadow-soft);
} }
.theme-toggle:hover { .theme-toggle:hover,
.route-toggle:hover {
background: var(--timeline-surface-strong); background: var(--timeline-surface-strong);
} }
.theme-toggle .button-icon { .theme-toggle .button-icon,
.route-toggle .button-icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
} }
@@ -980,6 +998,11 @@ function htmlPage(): string {
right: 12px; right: 12px;
} }
.top-right-controls {
top: 12px;
right: 12px;
}
.list { .list {
max-height: min(52vh, 420px); max-height: min(52vh, 420px);
--photo-thumb-size: 64px; --photo-thumb-size: 64px;
@@ -1007,14 +1030,25 @@ function htmlPage(): string {
</style> </style>
</head> </head>
<body data-theme="light"> <body data-theme="light">
<button class="secondary theme-toggle" id="theme-toggle" type="button" aria-label="Switch to dark mode"> <div class="top-right-controls">
<span class="button-icon" id="theme-toggle-icon" aria-hidden="true"> <button class="secondary theme-toggle" id="theme-toggle" type="button" aria-label="Switch to dark mode">
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <span class="button-icon" id="theme-toggle-icon" aria-hidden="true">
<path d="M8 1.8V3.1M8 12.9v1.3M3.1 3.1l.9.9M12 12l.9.9M1.8 8H3.1M12.9 8h1.3M3.1 12.9l.9-.9M12 4l.9-.9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/> <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="3.2" stroke="currentColor" stroke-width="1.4"/> <path d="M8 1.8V3.1M8 12.9v1.3M3.1 3.1l.9.9M12 12l.9.9M1.8 8H3.1M12.9 8h1.3M3.1 12.9l.9-.9M12 4l.9-.9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
</svg> <circle cx="8" cy="8" r="3.2" stroke="currentColor" stroke-width="1.4"/>
</span> </svg>
</button> </span>
</button>
<button class="secondary route-toggle" id="route-toggle" type="button" aria-label="Hide route line">
<span class="button-icon" id="route-toggle-icon" aria-hidden="true">
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 11.5 6.2 8.2c.4-.4 1-.5 1.5-.2l1.1.7c.5.3 1.1.2 1.5-.2L13 5.8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="3" cy="11.5" r="1" fill="currentColor"/>
<circle cx="13" cy="5.8" r="1" fill="currentColor"/>
</svg>
</span>
</button>
</div>
<main> <main>
<section class="map-panel"> <section class="map-panel">
<div id="map"></div> <div id="map"></div>
@@ -1182,11 +1216,13 @@ function htmlPage(): string {
color: "#2d6cdf", color: "#2d6cdf",
weight: 4, weight: 4,
opacity: 0.85 opacity: 0.85
}).addTo(map); });
const routeColors = { const routeColors = {
light: "#2d6cdf", light: "#2d6cdf",
dark: "#7dd3fc" dark: "#7dd3fc"
}; };
const ROUTE_VISIBLE_STORAGE_KEY = "routeVisible";
let routeVisible = localStorage.getItem(ROUTE_VISIBLE_STORAGE_KEY) !== "false";
const overlay = mustGet("overlay"); const overlay = mustGet("overlay");
const overlayTitle = mustGet("overlay-title"); const overlayTitle = mustGet("overlay-title");
@@ -1194,6 +1230,8 @@ function htmlPage(): string {
const overlayLoading = mustGet("overlay-loading"); const overlayLoading = mustGet("overlay-loading");
const overlayLoadingText = mustGet("overlay-loading-text"); const overlayLoadingText = mustGet("overlay-loading-text");
const closeOverlay = mustGet("close-overlay"); const closeOverlay = mustGet("close-overlay");
const routeToggle = mustGet("route-toggle");
const routeToggleIcon = mustGet("route-toggle-icon");
const photoList = mustGet("photo-list"); const photoList = mustGet("photo-list");
const emptyState = mustGet("empty-state"); const emptyState = mustGet("empty-state");
const photoCount = mustGet("photo-count"); const photoCount = mustGet("photo-count");
@@ -1362,6 +1400,36 @@ function htmlPage(): string {
}); });
} }
function setRouteVisible(visible) {
routeVisible = Boolean(visible);
localStorage.setItem(ROUTE_VISIBLE_STORAGE_KEY, routeVisible ? "true" : "false");
if (routeVisible) {
if (!map.hasLayer(route)) {
route.addTo(map);
}
routeToggle.setAttribute("aria-label", "Hide route line");
routeToggleIcon.innerHTML =
'<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M3 11.5 6.2 8.2c.4-.4 1-.5 1.5-.2l1.1.7c.5.3 1.1.2 1.5-.2L13 5.8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>' +
'<circle cx="3" cy="11.5" r="1" fill="currentColor"/>' +
'<circle cx="13" cy="5.8" r="1" fill="currentColor"/>' +
"</svg>";
} else {
if (map.hasLayer(route)) {
map.removeLayer(route);
}
routeToggle.setAttribute("aria-label", "Show route line");
routeToggleIcon.innerHTML =
'<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M3 11.5 6.2 8.2c.4-.4 1-.5 1.5-.2l1.1.7c.5.3 1.1.2 1.5-.2L13 5.8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>' +
'<circle cx="3" cy="11.5" r="1" fill="currentColor"/>' +
'<circle cx="13" cy="5.8" r="1" fill="currentColor"/>' +
'<path d="M3 13 13 3" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>' +
"</svg>";
}
}
function scheduleMapResize() { function scheduleMapResize() {
window.clearTimeout(scheduleMapResize.timeoutId); window.clearTimeout(scheduleMapResize.timeoutId);
scheduleMapResize.timeoutId = window.setTimeout(() => { scheduleMapResize.timeoutId = window.setTimeout(() => {
@@ -1416,6 +1484,10 @@ function htmlPage(): string {
themeToggle.addEventListener("click", () => { themeToggle.addEventListener("click", () => {
setTheme(document.body.dataset.theme === "dark" ? "light" : "dark"); setTheme(document.body.dataset.theme === "dark" ? "light" : "dark");
}); });
setRouteVisible(routeVisible);
routeToggle.addEventListener("click", () => {
setRouteVisible(!routeVisible);
});
const storedSidebarCollapsed = localStorage.getItem("sidebarCollapsed") === "true"; const storedSidebarCollapsed = localStorage.getItem("sidebarCollapsed") === "true";
setSidebarCollapsed(storedSidebarCollapsed); setSidebarCollapsed(storedSidebarCollapsed);