From 92a37ddac9031557605f7987292d5d5acaea5f92 Mon Sep 17 00:00:00 2001 From: Meysam Parvizi Date: Sun, 11 Oct 2026 17:12:17 +0200 Subject: [PATCH] feat(explorer): move zoom controls into the map toolbar --- explorer/map.css | 73 ++++++++++++++++++++++++++++++++++----------- explorer/mapview.js | 20 +++++++++---- 2 files changed, 69 insertions(+), 24 deletions(-) diff --git a/explorer/map.css b/explorer/map.css index 4dbc231..7a98191 100644 --- a/explorer/map.css +++ b/explorer/map.css @@ -473,29 +473,44 @@ } .zoom-controls { - position: absolute; - right: 16px; - bottom: 16px; - display: grid; - justify-items: center; - gap: 6px; - padding: 6px; - border: 1px solid var(--border); - border-radius: 14px; - background: var(--surface); - backdrop-filter: blur(10px); + display: flex; + align-items: center; + gap: 2px; + margin-left: auto; + padding: 1px; + border: 1px solid var(--border-strong); + border-radius: 999px; + background: var(--surface-2); } .zoom-controls .icon-btn { - width: 34px; - height: 34px; - font-size: 18px; + width: 26px; + height: 26px; + border: 0; + border-radius: 999px; + background: transparent; + font-size: 17px; font-weight: 700; } +.zoom-controls .icon-btn:hover { + background: var(--chip-hover); +} + +.btn-icon { + display: block; + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + .zoom-level { + min-width: 40px; color: var(--muted); - font-size: 11px; + font-size: 12px; + text-align: center; font-variant-numeric: tabular-nums; } @@ -527,10 +542,32 @@ .menu-list { min-width: 0; } +} - .zoom-controls { - bottom: 12px; - right: 12px; +/* Phones pinch to zoom, so the bar keeps only the fit button. */ +@media (max-width: 600px) { + .map-top { + padding: 6px 8px; + } + + .map-toolbar { + gap: 4px; + } + + .map-toolbar .map-chip { + padding: 4px 9px; + } + + .zoom-controls .zoom-step, + .zoom-level, + .map-chip .label-long { + display: none; + } +} + +@media (min-width: 601px) { + .map-chip .label-short { + display: none; } } diff --git a/explorer/mapview.js b/explorer/mapview.js index 4b8bd52..7993eab 100644 --- a/explorer/mapview.js +++ b/explorer/mapview.js @@ -105,7 +105,7 @@ export function createMapView({ root, plan, data, build, onSelect }) { h('p', { class: 'menu-heading' }, 'Importance'), h('div', { class: 'menu-chips' }, importanceChips.map(([, el]) => el)), clearButton); - const linksChip = chip('All connections', 'links', () => { + const linksChip = chip([h('span', { class: 'label-long' }, 'All connections'), h('span', { class: 'label-short' }, 'Links')], 'links', () => { state.showAll = !state.showAll; refresh(); }, 'Show the lines between all related topics'); @@ -605,16 +605,24 @@ export function createMapView({ root, plan, data, build, onSelect }) { }); const zoomLevel = h('span', { class: 'zoom-level', 'aria-live': 'polite' }, '100%'); - const fitButton = h('button', { type: 'button', class: 'icon-btn', 'aria-label': 'Toggle between fitting the width and the whole page', title: 'Show the whole page', onclick: toggleFit }, '⤢'); - const zoomControls = h('div', { class: 'zoom-controls' }, - h('button', { type: 'button', class: 'icon-btn', 'aria-label': 'Zoom in', title: 'Zoom in (Ctrl + scroll)', onclick: () => zoomAt(1.25) }, '+'), + // Drawn as SVG: text glyphs sit on font baselines that differ between browsers. + const btnIcon = (d) => { + const el = svg('svg', { viewBox: '0 0 16 16', width: 14, height: 14, 'aria-hidden': 'true', class: 'btn-icon' }); + svg('path', { d }, el); + return el; + }; + const fitButton = h('button', { type: 'button', class: 'icon-btn zoom-fit', 'aria-label': 'Toggle between fitting the width and the whole page', title: 'Show the whole page', onclick: toggleFit }, + btnIcon('M9.5 2.5h4v4M13.5 2.5 9 7M6.5 13.5h-4v-4M2.5 13.5 7 9')); + const zoomControls = h('div', { class: 'zoom-controls', role: 'group', 'aria-label': 'Zoom' }, + h('button', { type: 'button', class: 'icon-btn zoom-step', 'aria-label': 'Zoom out', title: 'Zoom out (Ctrl + scroll)', onclick: () => zoomAt(1 / 1.25) }, btnIcon('M3 8h10')), zoomLevel, - h('button', { type: 'button', class: 'icon-btn', 'aria-label': 'Zoom out', title: 'Zoom out (Ctrl + scroll)', onclick: () => zoomAt(1 / 1.25) }, '−'), + h('button', { type: 'button', class: 'icon-btn zoom-step', 'aria-label': 'Zoom in', title: 'Zoom in (Ctrl + scroll)', onclick: () => zoomAt(1.25) }, btnIcon('M3 8h10M8 3v10')), fitButton); + toolbar.append(zoomControls); root.replaceChildren( h('div', { class: 'map-top' }, toolbar), - h('div', { class: 'map-canvas' }, chart, zoomControls), + h('div', { class: 'map-canvas' }, chart), tip, ); fitWidth();