Add CSS-based fullscreen for Map tab; fix state desync bug
- Add fullscreen toggle button (⛶/✕) to Map tab controls row - CSS class `map-fs` hides header/nav and expands map to fill screen - Drop unreliable requestFullscreen() API (blocked on iOS/PWA) in favor of pure CSS approach - Fix button state desync: syncBtn() runs on init so stale ✕ state can't persist across reloads - Shrink embedded radar height on mobile (220px) and tune dvh calculations for safe-area insets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
48ae797520
commit
b9e6cad190
3 files changed
+106
-36
No files matched your search
@@ -1089,6 +1089,37 @@ const radarFull = radarFullEl
|
||||
)
|
||||
: { map: null, panTo: () => {}, startPlay: () => {}, stopPlay: () => {}, refresh: () => {} };
|
||||
|
||||
(function initMapFullscreen() {
|
||||
const fsBtn = document.getElementById('map-fullscreen-btn');
|
||||
if (!fsBtn) return;
|
||||
|
||||
function isFs() { return document.body.classList.contains('map-fs'); }
|
||||
|
||||
function syncBtn() {
|
||||
if (isFs()) { fsBtn.textContent = '✕'; fsBtn.title = 'Exit fullscreen'; }
|
||||
else { fsBtn.textContent = '⛶'; fsBtn.title = 'Fullscreen'; }
|
||||
}
|
||||
|
||||
function enterFs() {
|
||||
document.body.classList.add('map-fs');
|
||||
syncBtn();
|
||||
setTimeout(() => { unifiedMap && unifiedMap.refresh && unifiedMap.refresh(); }, 120);
|
||||
}
|
||||
|
||||
function exitFs() {
|
||||
document.body.classList.remove('map-fs');
|
||||
syncBtn();
|
||||
setTimeout(() => { unifiedMap && unifiedMap.refresh && unifiedMap.refresh(); }, 120);
|
||||
}
|
||||
|
||||
// Sync on load in case of stale state
|
||||
syncBtn();
|
||||
|
||||
fsBtn.addEventListener('click', () => {
|
||||
if (isFs()) exitFs(); else enterFs();
|
||||
});
|
||||
})();
|
||||
|
||||
function createOverviewMap(mapEl) {
|
||||
const map = new maplibregl.Map({
|
||||
container: mapEl,
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
<div class="section-head">
|
||||
<span class="section-label">Radar</span>
|
||||
<span class="section-note">
|
||||
<button class="link-btn" id="open-map-tab">Open full map →</button>
|
||||
<button class="link-btn" id="open-map-tab">Open map →</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="radar-embed-wrap" id="radar-embed-wrap">
|
||||
@@ -257,6 +257,7 @@
|
||||
<option value="light">Light</option>
|
||||
<option value="satellite">Satellite</option>
|
||||
</select>
|
||||
<button id="map-fullscreen-btn" class="radar-btn radar-fs-btn" title="Fullscreen">⛶</button>
|
||||
</div>
|
||||
|
||||
<div class="map-layer-menu">
|
||||
|
||||
+73
-35
@@ -1642,18 +1642,85 @@ details[open] .drawer-chevron { transform: rotate(90deg); }
|
||||
}
|
||||
|
||||
.radar-map-full {
|
||||
height: calc(100vh - 280px);
|
||||
min-height: 420px;
|
||||
height: calc(100dvh - 290px);
|
||||
min-height: 320px;
|
||||
}
|
||||
|
||||
.radar-full-wrap {
|
||||
border: var(--surface-border);
|
||||
border-radius: var(--surface-radius-md);
|
||||
background: #1a1f2e;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Fullscreen toggle button */
|
||||
.radar-fs-btn {
|
||||
background: var(--paper-dark);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--ink);
|
||||
font-size: 1.1rem;
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ── Map fullscreen mode (CSS-based, works on iOS Safari) ── */
|
||||
body.map-fs .masthead,
|
||||
body.map-fs .bottom-nav,
|
||||
body.map-fs .offline-banner,
|
||||
body.map-fs .ptr-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.map-fs .app {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
body.map-fs #tab-unified-map {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body.map-fs .unified-map-wrap {
|
||||
height: 100dvh;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: #1a1f2e;
|
||||
}
|
||||
|
||||
body.map-fs .map-controls-header {
|
||||
padding: 0.3rem 0.65rem;
|
||||
gap: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
body.map-fs .map-controls-row label,
|
||||
body.map-fs .map-controls-row select,
|
||||
body.map-fs .map-layer-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.map-fs .map-controls-row {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
body.map-fs #data-panel {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.map-fs .unified-map-shell {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
body.map-fs #unified-map {
|
||||
height: 100% !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/* ── Radar controls ── */
|
||||
.radar-controls {
|
||||
display: flex;
|
||||
@@ -1840,7 +1907,7 @@ details[open] .drawer-chevron { transform: rotate(90deg); }
|
||||
padding-bottom: max(4rem, calc(2rem + env(safe-area-inset-bottom)));
|
||||
}
|
||||
.radar-map-full {
|
||||
height: calc(100vh - 280px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
|
||||
height: calc(100dvh - 290px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
|
||||
}
|
||||
.map-overview {
|
||||
height: calc(100vh - 470px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
|
||||
@@ -1942,36 +2009,6 @@ details[open] .drawer-chevron { transform: rotate(90deg); }
|
||||
.tabs { display: none; }
|
||||
.bottom-nav { display: flex; }
|
||||
|
||||
#tab-radar-full {
|
||||
padding-bottom: max(6.4rem, calc(5.7rem + env(safe-area-inset-bottom, 0px)));
|
||||
}
|
||||
|
||||
.radar-controls-full {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto minmax(0, 1fr);
|
||||
grid-template-areas:
|
||||
'play layer ts'
|
||||
'timeline timeline timeline';
|
||||
gap: 0.45rem 0.5rem;
|
||||
padding: 0.55rem 0.65rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.radar-controls-full .play-btn { grid-area: play; }
|
||||
.radar-controls-full .layer-btn { grid-area: layer; }
|
||||
.radar-controls-full .radar-ts {
|
||||
grid-area: ts;
|
||||
min-width: 0;
|
||||
text-align: right;
|
||||
font-size: 0.66rem;
|
||||
}
|
||||
|
||||
.radar-controls-full .radar-timeline {
|
||||
grid-area: timeline;
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.radar-controls-full .radar-legend { display: none; }
|
||||
.radar-attribution {
|
||||
overflow-wrap: anywhere;
|
||||
@@ -2061,7 +2098,8 @@ details[open] .drawer-chevron { transform: rotate(90deg); }
|
||||
.recs-grid { grid-template-columns: repeat(3, 1fr); }
|
||||
.day-row { grid-template-columns: 80px 36px 1fr 70px; }
|
||||
.day-meta { display: none; }
|
||||
.radar-map { height: 240px; }
|
||||
.radar-embed-wrap .radar-map { height: 220px; }
|
||||
.radar-map-full { height: calc(100dvh - 330px); min-height: 250px; }
|
||||
.legend-bar { width: 50px; }
|
||||
.settings-row { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
|
||||
.settings-value { text-align: left; }
|
||||
|
||||
Reference in new issue
Block a user