From 6927efca542cc11a5bf91830feb96680b8bd081e Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sat, 28 Feb 2026 10:02:14 +0000 Subject: [PATCH] Add mobile bottom-sheet layout On narrow screens the sidebar collapses to a 48px handle strip at the bottom of the screen. Tapping the handle slides the panel up to 65vh, revealing the full stop list and controls. The map takes the full viewport width when the panel is closed or peek-visible. The handle label updates dynamically to show the loaded route name. The panel auto-opens when a route or route_master finishes loading. Co-Authored-By: Claude Sonnet 4.6 --- web/static/app.js | 21 ++++++++++++++ web/static/style.css | 59 ++++++++++++++++++++++++++++++++++++++++ web/templates/index.html | 10 +++++++ 3 files changed, 90 insertions(+) diff --git a/web/static/app.js b/web/static/app.js index 72f645a..9bd6ada 100644 --- a/web/static/app.js +++ b/web/static/app.js @@ -30,6 +30,23 @@ let activeSlot = 'from'; // 'from' | 'to' | null let selectedFrom = null; // stop name string or null let selectedTo = null; // stop name string or null +// ── Mobile panel ─────────────────────────────────────────────────────────── + +function isMobile() { return window.innerWidth < 768; } + +function openPanel() { + document.getElementById('sidebar').classList.add('panel-open'); +} + +function updateHandleLabel(text) { + const el = document.getElementById('sidebar-handle-label'); + if (el) el.textContent = text; +} + +document.getElementById('sidebar-handle').addEventListener('click', () => { + document.getElementById('sidebar').classList.toggle('panel-open'); +}); + // ── Helpers ──────────────────────────────────────────────────────────────── /** @@ -351,6 +368,8 @@ async function loadRoute(relationId) { document.getElementById('route-panel').classList.remove('d-none'); document.getElementById('route-name').textContent = data.name; document.title = `${data.name} – ${DEFAULT_TITLE}`; + updateHandleLabel(data.name); + if (isMobile()) openPanel(); document.getElementById('route-osm-link').href = `https://www.openstreetmap.org/relation/${relationId}`; @@ -440,6 +459,8 @@ async function loadRouteMaster(relationId) { document.getElementById('route-master-panel').classList.remove('d-none'); document.getElementById('route-master-name').textContent = data.name; document.title = `${data.name} – ${DEFAULT_TITLE}`; + updateHandleLabel(data.name); + if (isMobile()) openPanel(); document.getElementById('route-master-osm-link').href = `https://www.openstreetmap.org/relation/${relationId}`; diff --git a/web/static/style.css b/web/static/style.css index 6bef7ef..cb7abf1 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -10,10 +10,69 @@ html, body { #sidebar { height: 100%; min-height: 0; /* flex items default to min-height:auto, preventing overflow scrolling */ + overflow: hidden; + display: flex; + flex-direction: column; +} + +#sidebar-inner { overflow-y: auto; + flex: 1; padding: 1rem 1rem 0; /* no bottom padding — WebKit ignores it on overflow containers */ } +/* ── Mobile bottom sheet ───────────────────────────────── */ + +#sidebar-handle { + height: 48px; + flex-shrink: 0; + cursor: pointer; + user-select: none; + border-bottom: 1px solid #f0f0f0; + background: #fff; + border-radius: 16px 16px 0 0; +} + +#sidebar-handle-pill { + width: 36px; + height: 4px; + border-radius: 2px; + background: #ced4da; + flex-shrink: 0; +} + +@media (max-width: 767.98px) { + #sidebar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + width: 100% !important; + max-width: 100% !important; + flex: none !important; + height: 65vh; + max-height: calc(100vh - 56px); + min-height: unset; + transform: translateY(calc(100% - 48px)); + transition: transform 0.3s ease; + z-index: 1000; + border-radius: 16px 16px 0 0; + border-right: none !important; + box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.15); + background: #fff; + } + + #sidebar.panel-open { + transform: translateY(0); + } + + #map { + width: 100% !important; + max-width: 100% !important; + flex: 0 0 100% !important; + } +} + #map { height: 100%; } diff --git a/web/templates/index.html b/web/templates/index.html index 87f228f..ec3cc16 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -23,6 +23,15 @@