fix: comprehensive mobile responsive fixes for all pages

Live page (priority):
- Fix feed panel max-height from 180px to 40vh (was clipping content)
- Fix VCR bar: bump breakpoint from 600px to 640px, hide LCD, ensure
  no wrapping, increase touch targets to 44px min
- Remove rogue ≤600px rules that hid feed/legend/toggle entirely
- Fix legend toggle: was using inverted logic (legend-mobile-hidden
  toggled off instead of legend-mobile-visible toggled on)
- Header: constrain width to viewport, reduce padding/font on mobile
- Feed detail card: add max-height 50vh + overflow-y auto to prevent
  clipping off screen
- Disable feed resize handle on mobile (not practical for touch)
- Ensure Leaflet zoom controls clear mobile header

Packets page:
- panel-left gets min-height 50vh + overflow-x with -webkit touch scrolling
- data-table gets min-width 500px so it scrolls horizontally instead of
  collapsing columns to nothing
- panel-right removes max-height 50vh cap (was hiding detail panel)
- Filter bar buttons get 44px min touch target
- Node filter wrap goes full width

Nodes page:
- Node count pills wrap properly
- Smaller font on count pills for narrow screens

Analytics pages:
- analytics-grid goes single column on mobile
- analytics-page reduces padding

Style fixes (global):
- Filter bar gap reduced to 4px on mobile
- All cache busters updated
This commit is contained in:
you
2026-03-19 23:44:44 +00:00
parent d108f4dfaa
commit c97ff6da1f
4 changed files with 50 additions and 27 deletions
+3 -3
View File
@@ -20,9 +20,9 @@
<meta name="twitter:title" content="MeshCore Analyzer">
<meta name="twitter:description" content="Real-time MeshCore LoRa mesh network analyzer — live packet visualization, node tracking, channel decryption, and route analysis.">
<meta name="twitter:image" content="https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/public/og-image.png">
<link rel="stylesheet" href="style.css?v=1773963309">
<link rel="stylesheet" href="style.css?v=1773963867">
<link rel="stylesheet" href="home.css">
<link rel="stylesheet" href="live.css?v=1773963702">
<link rel="stylesheet" href="live.css?v=1773963867">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin="anonymous">
@@ -84,7 +84,7 @@
<script src="nodes.js?v=1773961950" onerror="console.error('Failed to load:', this.src)"></script>
<script src="traces.js?v=1774079160" onerror="console.error('Failed to load:', this.src)"></script>
<script src="analytics.js?v=1773961035" onerror="console.error('Failed to load:', this.src)"></script>
<script src="live.js?v=1773963609" onerror="console.error('Failed to load:', this.src)"></script>
<script src="live.js?v=1773963867" onerror="console.error('Failed to load:', this.src)"></script>
<script src="observers.js?v=1774079160" onerror="console.error('Failed to load:', this.src)"></script>
<script src="node-analytics.js?v=1773961276" onerror="console.error('Failed to load:', this.src)"></script>
</body>
+32 -16
View File
@@ -254,14 +254,20 @@
/* ---- Responsive ---- */
@media (max-width: 640px) {
.live-feed { width: calc(100vw - 24px); max-height: 180px; }
.live-legend { display: none; }
.live-legend.legend-mobile-hidden { display: none !important; }
.live-feed { width: calc(100vw - 24px); max-height: 40vh; }
/* Legend: hidden by default on mobile, toggle button shows it */
.live-legend { display: none !important; }
.live-legend.legend-mobile-visible { display: flex !important; }
.legend-toggle-btn { display: block !important; }
.live-legend:not(.legend-mobile-hidden) { display: flex !important; }
.live-header { flex-wrap: wrap; gap: 8px; }
.live-stats-row { flex-wrap: wrap; }
.live-header { flex-wrap: wrap; gap: 6px; }
/* Header: compact on mobile */
.live-header {
flex-wrap: wrap; gap: 6px; padding: 6px 10px;
top: 56px; left: 8px; right: 8px; max-width: calc(100vw - 16px);
}
.live-stats-row { flex-wrap: wrap; gap: 4px; }
.live-stat-pill { font-size: 11px; padding: 2px 7px; }
.live-toggles { font-size: 10px; gap: 6px; margin-left: 0; }
.live-title { font-size: 12px; letter-spacing: 1px; }
/* Feed detail card as bottom sheet on mobile (#61) */
.feed-detail-card {
position: fixed !important;
@@ -272,10 +278,20 @@
transform: none !important;
width: 100% !important;
max-width: 100vw !important;
max-height: 50vh !important;
overflow-y: auto !important;
border-radius: 10px 10px 0 0 !important;
animation: slideUp 0.2s ease-out !important;
}
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
/* Touch targets */
.feed-hide-btn { width: 36px; height: 36px; font-size: 16px; }
.feed-show-btn { padding: 10px 12px; min-width: 44px; min-height: 44px; }
.legend-toggle-btn { min-width: 44px; min-height: 44px; }
/* Feed resize handle: disable on mobile (can't drag easily) */
.feed-resize-handle { display: none; }
/* Leaflet zoom controls */
.live-page .leaflet-top.leaflet-right { top: 56px; }
}
/* Feed item hover */
@@ -605,15 +621,15 @@
.feed-show-btn { bottom: 68px !important; }
/* Mobile VCR */
@media (max-width: 600px) {
.vcr-bar { padding: 4px 6px; overflow-x: auto; flex-wrap: nowrap; }
.vcr-btn { padding: 6px 10px; font-size: 0.8rem; min-height: 36px; min-width: 36px; }
.vcr-scope-btn { font-size: 0.7rem; padding: 4px 8px; min-height: 36px; }
.vcr-lcd { display: flex; }
.live-feed { display: none; }
.feed-show-btn { display: none !important; }
.live-legend { display: none; }
.legend-toggle-btn { display: none !important; }
@media (max-width: 640px) {
.vcr-bar { padding: 4px 6px; overflow: hidden; flex-wrap: nowrap; }
.vcr-btn { padding: 6px 8px; font-size: 0.8rem; min-height: 44px; min-width: 44px; }
.vcr-scope-btns { gap: 1px; }
.vcr-scope-btn { font-size: 0.65rem; padding: 4px 6px; min-height: 36px; }
.vcr-lcd { display: none; }
.vcr-mode { font-size: 0.65rem; padding: 2px 6px; }
.vcr-timeline-container { min-width: 60px; }
.vcr-prompt { font-size: 0.7rem; }
}
/* Timeline time tooltip */
+3 -3
View File
@@ -729,9 +729,9 @@
const legendToggleBtn = document.getElementById('legendToggleBtn');
if (legendToggleBtn && legendEl) {
legendToggleBtn.addEventListener('click', () => {
const isHidden = legendEl.classList.toggle('legend-mobile-hidden');
legendToggleBtn.setAttribute('aria-label', isHidden ? 'Show legend' : 'Hide legend');
legendToggleBtn.textContent = isHidden ? '🎨' : '';
const isVisible = legendEl.classList.toggle('legend-mobile-visible');
legendToggleBtn.setAttribute('aria-label', isVisible ? 'Hide legend' : 'Show legend');
legendToggleBtn.textContent = isVisible ? '' : '🎨';
});
}
+12 -5
View File
@@ -811,8 +811,8 @@ button.ch-item.selected { background: var(--selected-bg); }
/* Layouts: stack instead of side-by-side */
.split-layout { flex-direction: column; overflow-y: auto; }
.panel-left { padding: 10px; }
.panel-right { width: 100%; min-width: 0; border-left: none; border-top: 1px solid var(--border); max-height: 50vh; }
.panel-left { padding: 10px; flex: none; min-height: 50vh; overflow-x: auto; }
.panel-right { width: 100%; min-width: 0; border-left: none; border-top: 1px solid var(--border); max-height: none; flex: none; }
/* Channels: Discord-style full screen toggle */
.ch-layout { flex-direction: row; position: relative; }
@@ -834,16 +834,21 @@ button.ch-item.selected { background: var(--selected-bg); }
.data-table { font-size: 12px; }
.data-table td { padding: 6px 6px; max-width: 120px; }
.data-table th { padding: 6px 6px; font-size: 11px; }
.panel-left { overflow-x: auto; }
.panel-left { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.data-table { min-width: 500px; }
/* Filters: full width */
.filter-bar { flex-direction: column; }
.filter-bar { flex-direction: column; gap: 4px; }
.filter-bar input { width: 100%; }
.filter-bar select { width: 100%; }
.filter-bar .btn { min-height: 44px; }
.node-filter-wrap { width: 100%; }
/* Nodes */
.nodes-topbar { flex-direction: column; gap: 8px; padding: 10px; }
.nodes-tabs-bar { flex-direction: column; }
.nodes-counts { flex-wrap: wrap; }
.node-count-pill { font-size: 11px; padding: 2px 8px; }
/* Traces */
.trace-summary { flex-direction: column; }
@@ -854,7 +859,7 @@ button.ch-item.selected { background: var(--selected-bg); }
.search-overlay { padding-top: 60px; }
/* Map controls */
.map-controls { width: calc(100vw - 24px); right: 12px; top: 8px; max-height: 200px; }
.map-controls { width: calc(100vw - 24px); right: 12px; top: 8px; max-height: 200px; font-size: 12px; padding: 10px 12px; }
#leaflet-map { z-index: 0; }
#map-wrap { z-index: 0; }
@@ -1087,6 +1092,8 @@ button.ch-item.ch-item-encrypted .ch-badge { filter: grayscale(0.6); }
.stats-grid { grid-template-columns: repeat(2, 1fr); }
.repeater-name { min-width: 80px; }
.reach-ring { flex-wrap: wrap; }
.analytics-page { padding: 12px; }
.analytics-grid { grid-template-columns: 1fr; }
}
.observer-selector { display: flex; gap: 4px; margin-bottom: 12px; flex-wrap: wrap; }
.node-qr { text-align: center; margin-top: 8px; }