From fdb06b8b565c1152070ce5e26b504584bd327f54 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 09:26:50 +0000 Subject: [PATCH] Phone pages: the app's height no longer changes as the address bar hides or shows The host page of every full-page map (and the Plugin Studio) sized the element to the viewport in a way that tracks the phone's address bar: - the built fixed-viewport leaf used position:fixed with inset:0, which follows the DYNAMIC viewport, so the map and its legend sheet resized on every scroll that moved the bar; - the Plugin Studio page and the dev server's leaf and studio pages used 100vh, the LARGE viewport, taller than the view while the bar shows, so the page itself scrolled by the bar's height and the app seemed to resize. All four now use height:100svh (100% first as the fallback where svh is unknown), anchored top-left, and set --profile-min-h:0 so ProfileLoader's 100dvh floor cannot grow the element when the bar hides. On a desktop svh equals the viewport, so nothing moves there. Scroll-page leaves (the cap-4 stacks) are unchanged. Regenerated the tree: 51 leaf pages and the Plugin Studio page change only this rule and its comment; no bundle changes. --- internal/generate-tree.mjs | 17 ++++++++++++++--- internal/plugin-gallery/dev-plugin.mjs | 7 +++++-- .../all-people-groups/index.html | 10 ++++++++-- .../connectivity-list/index.html | 10 ++++++++-- .../cities-internet/connectivity-map/index.html | 10 ++++++++-- .../cities-internet/data-tables/index.html | 10 ++++++++-- .../dx-maps/country-map/country-map/index.html | 10 ++++++++-- .../country-posters/countries-map/index.html | 10 ++++++++-- .../country-poster-wall/index.html | 10 ++++++++-- public/dx-maps/demo-map/demo-map/index.html | 10 ++++++++-- .../demo-map/demo-map/maplibre/index.html | 10 ++++++++-- .../doxa-maps-spa/doxa-maps-spa/app/index.html | 10 ++++++++-- .../doxa-maps-spa/doxa-maps-spa/index.html | 10 ++++++++-- .../doxa-research-map/research-map/index.html | 10 ++++++++-- .../research-map/maplibre/index.html | 10 ++++++++-- .../doxa-simple-map/adoption/index.html | 10 ++++++++-- .../doxa-simple-map/engagement/index.html | 10 ++++++++-- .../doxa-simple-map/doxa-simple-map/index.html | 10 ++++++++-- .../doxa-simple-map/prayer/index.html | 10 ++++++++-- .../doxa-vision-card/default/index.html | 10 ++++++++-- .../doxa-vision-card/frontier/index.html | 10 ++++++++-- .../doxa-vision-card/index.html | 10 ++++++++-- .../golden-path-check/index.html | 10 ++++++++-- .../gospel-internet/board/board/index.html | 10 ++++++++-- public/dx-maps/gospel-internet/board/index.html | 10 ++++++++-- .../board/india-china/index.html | 10 ++++++++-- .../board/language-tree/index.html | 10 ++++++++-- .../gospel-internet/board/platforms/index.html | 10 ++++++++-- .../board/project-700/index.html | 10 ++++++++-- .../gospel-internet/board/zero/index.html | 10 ++++++++-- .../dx-maps/gospel-resources/charts/index.html | 10 ++++++++-- .../gospel-resources/data-tables/index.html | 10 ++++++++-- .../gospel-resources/resources-list/index.html | 10 ++++++++-- .../gospel-resources/resources-map/index.html | 10 ++++++++-- public/dx-maps/index.html | 7 ++++++- .../my-upg-100-list/poster-wall/index.html | 10 ++++++++-- .../my-upg-100-list/upg-100-list/index.html | 10 ++++++++-- .../people-groups-grid/driven/index.html | 10 ++++++++-- .../people-groups-grid/index.html | 10 ++++++++-- .../people-groups-grid/index.html | 10 ++++++++-- .../plugin-studio/plugin-studio/index.html | 10 ++++++++-- .../plugin-studio/studio/index.html | 10 ++++++++-- .../pplr-data-maps/pplr-data-maps/index.html | 10 ++++++++-- .../prayer-walk-planner/index.html | 10 ++++++++-- .../region-dashboards/index.html | 10 ++++++++-- .../regions-dashboard/regions-list/index.html | 10 ++++++++-- .../research-dashboard/index.html | 10 ++++++++-- .../upg-neighbor/bloom-cockpit/index.html | 10 ++++++++-- .../upg-neighbor/flower-mesh/index.html | 10 ++++++++-- .../upg-neighbor/upg-neighbor/index.html | 10 ++++++++-- .../upg-neighbor/lang-cluster/index.html | 10 ++++++++-- .../upg-neighbor/send-map/index.html | 10 ++++++++-- .../upg-neighbor/upg-neighbors/index.html | 10 ++++++++-- .../wall-of-people-groups/index.html | 10 ++++++++-- 54 files changed, 433 insertions(+), 108 deletions(-) diff --git a/internal/generate-tree.mjs b/internal/generate-tree.mjs index c178a03e1..60529df7f 100644 --- a/internal/generate-tree.mjs +++ b/internal/generate-tree.mjs @@ -798,7 +798,12 @@ function studioRootHtml(bakedToken, integrity = '') { ${bakedToken ? ` \n` : ''}${DEST_CONFIG.apiBaseUrl ? ` \n` : ''} @@ -1027,9 +1032,15 @@ ${hintBlock} ${peerBlock} font: 13px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; } #status.err { color: #f87171; }` : `/* BARE full-page map — no chrome. The custom element IS the page, so the - browser URL shares the map itself. */ + browser URL shares the map itself. + HEIGHT IN svh, NOT inset:0. A fixed box with inset:0 follows the phone's DYNAMIC viewport, so the map + (and a legend sheet sized from it) changes height every time the address bar hides or shows. 100svh is + the viewport WITH the bar shown and never changes; when the bar hides, the page background shows below + instead of the map resizing. On a desktop svh = the viewport, so nothing moves there. The 100% before it + is the fallback for a browser without svh, which would otherwise size the box to its content. + --profile-min-h:0 opts out of ProfileLoader's 100dvh floor, which would grow the element again. */ html, body { height: 100%; margin: 0; background: #0a0e15; } - #slot, ${esc(tag)} { position: fixed; inset: 0; width: 100%; height: 100%; display: block; } + #slot, ${esc(tag)} { position: fixed; inset: 0 auto auto 0; width: 100%; height: 100%; height: 100svh; --profile-min-h: 0; display: block; } #status { position: fixed; inset: 0; z-index: 2; display: grid; place-items: center; padding: 24px; text-align: center; color: #9aa7b8; font: 13px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; } diff --git a/internal/plugin-gallery/dev-plugin.mjs b/internal/plugin-gallery/dev-plugin.mjs index 26eca3a9c..5b6ff2b62 100644 --- a/internal/plugin-gallery/dev-plugin.mjs +++ b/internal/plugin-gallery/dev-plugin.mjs @@ -417,7 +417,10 @@ export function autoSpaDevPlugin(token = '') { // depends on no ancestor and stays a floor, so the page can still grow past it. `${tag}{display:block;width:100%;min-height:100dvh;}` : '`, + // 100svh (100% as the fallback), not 100vh: a phone's 100vh is taller than the view while the address + // bar shows, so the page scrolls by the bar and the app seems to resize; --profile-min-h:0 opts out of + // ProfileLoader's 100dvh floor. The same rule as generate-tree's fixed-viewport leaf. + `${tag}{display:block;width:100%;height:100%;height:100svh;--profile-min-h:0;}`, '', // tree-base ON THE LEAF TOO — cap-5 shells nested here fetch a manifest of their own. // doxa-maps-spa (like plugin-studio) discovers its tabs from the tree's manifest.json and @@ -483,7 +486,7 @@ export function autoSpaDevPlugin(token = '') { // that takes up so much space" is a layout requirement, so the host page contributes // ZERO text — every pixel belongs to the studio element. '', + 'plugin-studio{display:block;width:100%;height:100%;height:100svh;--profile-min-h:0;}', '', // tree-base IS REQUIRED IN DEV — without it the studio mounts EMPTY. // The studio builds its tab list at runtime by fetching `manifest.json`, and with diff --git a/public/dx-maps/all-people-groups/all-people-groups/index.html b/public/dx-maps/all-people-groups/all-people-groups/index.html index 77b413376..0f34812e8 100644 --- a/public/dx-maps/all-people-groups/all-people-groups/index.html +++ b/public/dx-maps/all-people-groups/all-people-groups/index.html @@ -26,9 +26,15 @@ check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). --> diff --git a/public/dx-maps/my-upg-100-list/poster-wall/index.html b/public/dx-maps/my-upg-100-list/poster-wall/index.html index 8cbc5aee8..d29e3c0f5 100644 --- a/public/dx-maps/my-upg-100-list/poster-wall/index.html +++ b/public/dx-maps/my-upg-100-list/poster-wall/index.html @@ -17,9 +17,15 @@ which loads its own map peer + token. A peer here would be dead weight + imply a gate. -->