From c5e12b904f98a54878010ed72e18083a202736ce Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Wed, 3 Jun 2026 14:14:07 -0700 Subject: [PATCH] Artist Map v2: mobile-responsive toolbar/header - Toolbar wraps on phones (<=760px): back + title + stats and the compact tools stay on row 1, the search drops to its own full-width row below so nothing gets crushed. Brand text hidden, stats truncate with ellipsis. - Island nav + canvas height now MEASURE the toolbar height instead of assuming ~50px, so the taller wrapped header doesn't overlap the nav or clip the canvas. 64 JS integrity tests pass. --- webui/static/discover.js | 13 +++++++++---- webui/static/style.css | 13 +++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/webui/static/discover.js b/webui/static/discover.js index cd8b9270..19ee8809 100644 --- a/webui/static/discover.js +++ b/webui/static/discover.js @@ -5322,10 +5322,13 @@ function _artMapUpdateIslandNav() { nav.id = 'artmap-island-nav'; container.appendChild(nav); } - // Position top-left, clearing the genre sidebar (when shown) and the toolbar. + // Position top-left, clearing the genre sidebar (when shown) and the toolbar + // (measured — the toolbar wraps taller on mobile). const sb = document.getElementById('artmap-genre-sidebar'); const sbW = (sb && sb.style.display !== 'none') ? (sb.offsetWidth || 0) : 0; - nav.style.cssText = `position:absolute;top:64px;left:${sbW + 16}px;display:flex;align-items:center;gap:12px;padding:7px 12px;background:rgba(16,12,28,0.82);backdrop-filter:blur(10px);border:1px solid rgba(168,85,247,0.25);border-radius:14px;z-index:30;box-shadow:0 6px 24px rgba(0,0,0,0.45);user-select:none;`; + const tb = document.querySelector('.artist-map-toolbar'); + const top = (tb ? tb.offsetHeight : 56) + 10; + nav.style.cssText = `position:absolute;top:${top}px;left:${sbW + 16}px;display:flex;align-items:center;gap:12px;padding:7px 12px;background:rgba(16,12,28,0.82);backdrop-filter:blur(10px);border:1px solid rgba(168,85,247,0.25);border-radius:14px;z-index:30;box-shadow:0 6px 24px rgba(0,0,0,0.45);user-select:none;max-width:calc(100vw - ${sbW + 32}px);`; const idx = _artMap._focusIdx || 0; const isl = islands[idx]; const btn = 'width:30px;height:30px;border-radius:50%;border:1px solid rgba(255,255,255,0.18);background:rgba(255,255,255,0.06);color:#fff;font-size:13px;cursor:pointer;display:flex;align-items:center;justify-content:center;flex:none;'; @@ -5697,7 +5700,8 @@ async function openArtistMap() { _artMap.canvas = canvas; _artMap.ctx = canvas.getContext('2d'); _artMap.width = container.clientWidth; - _artMap.height = container.clientHeight - 50; + const _wtb = container.querySelector('.artist-map-toolbar'); + _artMap.height = container.clientHeight - (_wtb ? _wtb.offsetHeight : 50); canvas.width = _artMap.width * window.devicePixelRatio; canvas.height = _artMap.height * window.devicePixelRatio; canvas.style.width = _artMap.width + 'px'; @@ -7067,7 +7071,8 @@ async function _openArtistMapExplorerWithName(name) { _artMap.canvas = canvas; _artMap.ctx = canvas.getContext('2d'); _artMap.width = container.clientWidth; - _artMap.height = container.clientHeight - 50; + const _wtb = container.querySelector('.artist-map-toolbar'); + _artMap.height = container.clientHeight - (_wtb ? _wtb.offsetHeight : 50); canvas.width = _artMap.width * window.devicePixelRatio; canvas.height = _artMap.height * window.devicePixelRatio; canvas.style.width = _artMap.width + 'px'; diff --git a/webui/static/style.css b/webui/static/style.css index 35afbdef..3abe87c9 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -34248,6 +34248,19 @@ div.artist-hero-badge { .artmap-tool-btn.artmap-zoom { border: none; background: none; width: 30px; padding: 0; justify-content: center; border-radius: 6px; } .artmap-tool-btn.artmap-zoom:hover { background: rgba(255,255,255,0.06); } +/* Mobile: the toolbar wraps — back/title/stats + compact tools on row 1, the + search drops to its own full-width row below so nothing gets crushed. */ +@media (max-width: 760px) { + .artist-map-toolbar { flex-wrap: wrap; padding: 8px 10px; gap: 8px; } + .artmap-nav-left { flex: 1 1 auto; min-width: 0; gap: 6px; } + .artmap-brand-text { display: none; } + .artmap-brand { flex: none; } + .artmap-stats { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .artmap-nav-right { flex: 0 0 auto; gap: 3px; } + .artmap-nav-center { order: 3; flex: 1 1 100%; max-width: none; margin: 0; } + .artmap-search-wrap { width: 100%; } +} + /* Shortcuts modal */ .artmap-shortcuts-modal { background: rgba(20,20,32,0.95); border-radius: 14px; width: 340px; max-width: 90vw;