Simple Research's map band ends on the first screen

On a phone under DX Life's header, the band ran 32px past the fold (y132 to y876 on an 844px
screen). The legend sheet's bottom and its collapsed strip began below the fold, so a reader who
collapsed the legend could not reopen it without scrolling. The band now takes the height that is
visible below its own top, capped at the old 88svh, which is also the fallback. It is measured once,
and again only on a width change, so the URL bar showing and hiding does not resize the map.
This commit is contained in:
Doxa Maps 2026-09-30 02:32:00 +00:00
parent 29634ed075
commit 76ba9c1a6d

View file

@ -226,7 +226,36 @@ const SHARE_URL = absoluteEmbedUrl('research-map-plus-grid/research-map-plus-gri
// Pinning min === max gives it a definite height to fill while the page keeps growing below.
// svh (small viewport height) avoids the mobile URL-bar jump — which matters MORE here than on the
// desktop sibling, because this composite is the mobile one.
const MAP_H = '88svh'
// ★ AND IT ENDS ON THE FIRST SCREEN. 88svh assumes the band starts near the top of the window.
// Under a host page's header it does not: measured 2026-09-30 on DX Life at 390x844, the band ran
// from y132 to y875. The legend sheet's bottom and its COLLAPSED strip began 31px below the fold,
// so a reader who collapsed the legend could not reopen it without scrolling first. sizeBand() below
// shortens the band to what is visible beneath its own top (never more than 88svh). The fallback is
// the old 88svh. It is measured once, and again only when the WIDTH changes (a rotation), never on a
// height change: the URL bar showing and hiding must not resize the map.
const MAP_H = 'var(--sr-band-h, 88svh)'
function scrollParentOf(el) {
for (let n = el.parentElement || el.getRootNode?.()?.host; n; n = n.parentElement || n.getRootNode?.()?.host) {
const oy = getComputedStyle(n).overflowY
if (oy === 'auto' || oy === 'scroll') return n
}
return null
}
let _bandWidth = 0
function sizeBand() {
try {
const host = _selfInstance?.proxy?.$el?.getRootNode?.()?.host
if (!host || !host.style || typeof window === 'undefined') return
const box = scrollParentOf(host)
const bottom = Math.min(window.innerHeight, box ? box.getBoundingClientRect().bottom : window.innerHeight)
const h = Math.floor(Math.min(bottom - Math.max(0, host.getBoundingClientRect().top), window.innerHeight * 0.88))
// Below 320px the map is worse than a band that runs past the fold, so keep the fallback there.
if (h >= 320) host.style.setProperty('--sr-band-h', h + 'px')
else host.style.removeProperty('--sr-band-h')
_bandWidth = window.innerWidth
} catch (_) { /* no layout (SSR/tests): the 88svh fallback stands */ }
}
function onBandResize() { if (window.innerWidth !== _bandWidth) sizeBand() }
// src is resolved by the browser relative to THIS leaf page, which is served two levels deep
// (doxa-maps/research-map-plus-grid/research-map-plus-grid/index.html) — so go UP TWO to reach a
@ -494,10 +523,14 @@ onMounted(() => {
rootEl = getCurrentInstance()?.proxy?.$el?.getRootNode?.() || null
rootEl?.addEventListener?.('groups-filtered', onGridFiltered)
rootEl?.addEventListener?.('map-filtered', onMapFiltered)
// After the first layout, so the host page's header has its height.
requestAnimationFrame(sizeBand)
window.addEventListener('resize', onBandResize)
})
onBeforeUnmount(() => {
rootEl?.removeEventListener?.('groups-filtered', onGridFiltered)
rootEl?.removeEventListener?.('map-filtered', onMapFiltered)
window.removeEventListener('resize', onBandResize)
})
const sections = computed(() => [