A back-to-top beside the view-list circle, and lift the Regions attribution clear of it
Two reported mobile bugs (DRV1650 #3 and #4), both settled by rega's
measurements at 390x844 on dx-life /research rather than by reading source.
★ #3 — THERE WAS NO BACK-TO-TOP AT ALL, and I had reported otherwise. I said
VerticalTabsLayout already rendered one targeting the active .vtl-host. rega:
ZERO .vtl-host elements in the live build, button.btt ABSENT from the DOM. The
chain: VTL renders .vtl-host only for `mountedElementRows`, which filters rows
carrying an `element` key — and this SPA passes :groups whose rows carry none,
mounting its own .dms-pane panes imperatively. So activeHostEl is null, and the
layout's button correctly renders nothing. That button is for layouts hosting
their own element rows; it is inert for the composition the gallery uses. I had
read the source and not the configuration.
The SPA now renders its own, bound to the ACTIVE .dms-pane — the scroller rega
measured (clientHeight 712, scrollHeight 12,373, overflow-y:auto) while the
document does not scroll at all. The gallery owns both the circle and the
scroller, so no shadow-root walking is needed. Placement reads --map-fab-beside,
published by the layout only while its circle renders, so the arrow sits BESIDE
the circle and falls back to the plain inset where there is none.
BackToTopButton already refuses to appear when its target does not scroll.
The label goes in all ELEVEN of the SPA's locales. Its translate() falls back to
the KEY, so a missing entry would have rendered the literal string "backToTop"
to every reader — en/ar/zh/ru/hi verified, and the Arabic and Chinese strings
are present in the built bundle.
★ #4 — THE REGIONS ATTRIBUTION SITS UNDER THE CIRCLE, and the geometry was not
what I assumed. rega: at 390 the attribution is details.maplibregl-ctrl-attrib in
the BOTTOM-RIGHT container, expanded to 347x44 at (22,791) — nearly the full map
width — so its LEFT END runs under the 44px fab at (12,788), 1,394 px² overlap.
The bottom-left container is EMPTY (0x0), so a bottom-left-only fix would have
changed nothing.
Both bottom containers are lifted off the published --map-fab-clearance under a
767px query, so a standalone leaf or a <doxa-country-map> with no gallery around
it reads the 0px fallback and nothing moves. The existing z-index:3 cannot help:
the circle lives in the layout, outside this shadow root, so the two are
different stacking contexts. Attribution is a LICENCE TERM of the basemap, which
is why this is a fix and not a polish item.
REBASED ONTO 0428f279c BY REPLAYING SOURCE, not by resolving a conflict: the
rebase collided only in generated bundles, where a conflict is never resolvable
by hand. Three files applied clean; RegionCountryMap.vue had MOVED to
library/components/maps in that same round (my own country-map work), so its rule
was re-applied at the new path by hand — a straight patch would have failed with
"No such file or directory", which is exactly what studio would have hit.
country-map, regions-dashboard and doxa-maps-spa rebuilt; both fixes verified in
the shipped minified bundles, including the new country-map bundle that now
inherits the lift.
NOT PROVEN HERE: the headless DOM proof needs a browser (rega's seat). What I
verified is that the button, its scoped CSS and its ar/zh labels are in the
SHIPPED doxa-maps-spa.js, and the fab lift in both map bundles.
This commit is contained in:
parent
b8166218b9
commit
65810f872f
9 changed files with 83 additions and 14 deletions
|
|
@ -58,7 +58,19 @@ useShadowStyles(`
|
|||
single tight row, slightly reduced and translucent. The corners sit just above the sheet's
|
||||
collapsed strip (48px), so the watermark is always visible when the legend is closed; an
|
||||
opened sheet covers it. */
|
||||
.mapboxgl-ctrl-bottom-left,.mapboxgl-ctrl-bottom-right,.maplibregl-ctrl-bottom-left,.maplibregl-ctrl-bottom-right{transform:translateY(calc(-1 * min(var(--legend-sheet-h,0px),48px)));}
|
||||
/* ★ THE FAB SITS ON THE ATTRIBUTION TOO, not just the sheet (rega at 390x844, dx-life
|
||||
/research: the gallery's 44px vtl-fab at (12,788) is topmost over Cities' bottom-left
|
||||
attribution line "…oundaries · OpenFreeMap"). This rule already lifted the engine's bottom
|
||||
corners clear of the legend SHEET; it never knew about the circle, which lives in the LAYOUT
|
||||
outside every plugin's shadow root and therefore paints over plugin content at any internal
|
||||
z-index. Attribution is a LICENCE TERM of the basemap, so a control covering it is not a
|
||||
cosmetic overlap.
|
||||
The lift is now the MAX of the two obstacles rather than the sheet alone: whichever is taller
|
||||
decides, and neither is double-counted, because the fab and the sheet occupy the same corner.
|
||||
Both are read from published variables — --legend-sheet-h (this component's own ResizeObserver)
|
||||
and --map-fab-clearance (VerticalTabsLayout, set ONLY while the circle renders) — so a map with
|
||||
no sheet and no fab still moves nothing. The 48px cap on the sheet term is kept as it was. */
|
||||
.mapboxgl-ctrl-bottom-left,.mapboxgl-ctrl-bottom-right,.maplibregl-ctrl-bottom-left,.maplibregl-ctrl-bottom-right{transform:translateY(calc(-1 * max(min(var(--legend-sheet-h,0px),48px), var(--map-fab-clearance,0px))));}
|
||||
/* The scroll-edge gutters (the hoverable side strips, z-index 2) run the full height of the
|
||||
map and would otherwise swallow taps meant for the attribution in the corner: the corner
|
||||
controls sit one tier above them. (Moves to the shared z tiers with the token work.) */
|
||||
|
|
|
|||
|
|
@ -839,6 +839,25 @@ useShadowStyles(
|
|||
'.mapboxgl-ctrl-top-right,.maplibregl-ctrl-top-right,' +
|
||||
'.mapboxgl-ctrl-bottom-left,.maplibregl-ctrl-bottom-left,' +
|
||||
'.mapboxgl-ctrl-bottom-right,.maplibregl-ctrl-bottom-right{ z-index:3; }' +
|
||||
// ★ LIFT THE BOTTOM CHROME CLEAR OF THE GALLERY'S VIEW-LIST CIRCLE (rega at 390x844 on
|
||||
// dx-life /research). The circle is button.vtl-fab, 44x44 at (12,788), and it lives in
|
||||
// VerticalTabsLayout — OUTSIDE this shadow root — so it paints over this map's chrome at any
|
||||
// z-index we set here; the two are different stacking contexts, which is why the z-index:3
|
||||
// above cannot help. MEASURED: the attribution is details.maplibregl-ctrl-attrib in the
|
||||
// BOTTOM-RIGHT container, expanded to 347x44 at (22,791) — nearly the full map width at 390 —
|
||||
// so its LEFT END runs under the circle (1,394 px² overlap). Attribution is a LICENCE TERM of
|
||||
// the basemap, not chrome we may cover.
|
||||
// BOTH corners are lifted, because at this width the right container spans the map and the left
|
||||
// one is empty (0x0) — lifting only the left would have fixed nothing here.
|
||||
// --map-fab-clearance is published by the layout ONLY while the circle renders, and custom
|
||||
// properties inherit through the flattened tree, so a standalone leaf or a <doxa-country-map>
|
||||
// with no gallery around it reads the 0px fallback and nothing moves. This component loads no
|
||||
// LegendMobile, which is where the same lift lives for the other four production maps.
|
||||
'@media (max-width: 767px){' +
|
||||
' .mapboxgl-ctrl-bottom-left,.maplibregl-ctrl-bottom-left,' +
|
||||
' .mapboxgl-ctrl-bottom-right,.maplibregl-ctrl-bottom-right{' +
|
||||
' transform:translateY(calc(-1 * var(--map-fab-clearance, 0px))); }' +
|
||||
'}' +
|
||||
// ★ THEIR GLOBAL BOX-SIZING RESET, which no scoped style could ever have shown me.
|
||||
// app/assets/styles/base/_reset.scss:3-8 is `*, *::before, *::after { box-sizing: border-box }`
|
||||
// (a piccalil.li reset) and it applies to every element on their page, the legend swatch
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@
|
|||
dropped the OLDEST one and an already-visited tab went blank with NO error. -->
|
||||
<section
|
||||
v-for="(t, i) in tabs" :key="t.id" class="dms-pane"
|
||||
:ref="el => { if (el) paneEls[i] = el; else delete paneEls[i] }"
|
||||
v-show="i === activeIndex" :hidden="i !== activeIndex"
|
||||
:data-doxa-help="tabHasHelp(t) ? '' : null">
|
||||
|
||||
|
|
@ -173,12 +174,26 @@
|
|||
<button ref="helpClose" type="button" class="dms-help-close" @click="closeHelp">{{ tr('close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ★ BACK TO TOP, BESIDE THE VIEW-LIST CIRCLE (DRV1650 #3). The gallery owns both the circle
|
||||
and the scroller, so this needs no shadow-root walking: the target is the ACTIVE .dms-pane,
|
||||
which rega measured as the real scroller (clientHeight 712, scrollHeight 12,373) while the
|
||||
document does not scroll and no .vtl-host exists in this composition.
|
||||
Horizontal placement comes from --map-fab-beside, which VerticalTabsLayout publishes ONLY
|
||||
while its circle renders (12px inset + 44px button + 8px gap), so the arrow sits next to the
|
||||
circle rather than on it — and where there is no circle it falls back to the plain inset
|
||||
instead of leaving a gap. Reading the var means the circle's geometry stays stated once, by
|
||||
the component that owns it.
|
||||
BackToTopButton refuses to appear when its target does not scroll (it tests scrollTop AND
|
||||
scrollHeight), so a short pane shows nothing rather than a button that does nothing. -->
|
||||
<BackToTopButton :target="activePaneEl" :labels="{ backToTop: tr('backToTop') }" />
|
||||
</VerticalTabsLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, inject } from 'vue'
|
||||
import VerticalTabsLayout from '@map/layouts/VerticalTabsLayout.vue'
|
||||
import BackToTopButton from '@map/components/BackToTopButton.vue'
|
||||
import { SWITCHER_LANGUAGES, loadLocale, saveLocale, getLanguage } from '@map/layouts/app-wrapper-material/languages.js'
|
||||
import { translate, LOCALES, hasKey } from './src/strings.js'
|
||||
import { helpFor } from './src/experimentalHelp.js'
|
||||
|
|
@ -728,7 +743,7 @@ export default defineComponent({
|
|||
// (measured 2026-09-25). .vtl survives today only because it declares display:grid !important.
|
||||
// Everything the layout needs (dir, lang, labels, …) is passed explicitly below.
|
||||
inheritAttrs: false,
|
||||
components: { VerticalTabsLayout },
|
||||
components: { VerticalTabsLayout, BackToTopButton },
|
||||
// profile-config props the standalone leaf page + gallery hand every element. treeBase lets a
|
||||
// host pin the tree root explicitly; the rest are accepted so the element is a well-behaved
|
||||
// member of the bundler (profile/instanceId/assetsBase/tk/shareUrl/qa are ignored here — the
|
||||
|
|
@ -778,6 +793,10 @@ export default defineComponent({
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
// The .dms-pane elements, one per tab, keyed by index. The SPA's pane IS the scroller
|
||||
// (overflow-y:auto), so the back-to-top has to follow activeIndex rather than bind one ref.
|
||||
// Not reactive-deep on purpose: these are DOM nodes.
|
||||
paneEls: {},
|
||||
activeIndex: 0,
|
||||
// The cap-5 DX-Maps SPA is HEADER-OFF by default (sidebar-only, full-page — no stacked headers
|
||||
// when embedded under a host that already has one). This ONE flag drives BOTH the shell header
|
||||
|
|
@ -835,6 +854,14 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
// ★ THE SCROLLER IS THIS PANE, MEASURED, NOT VTL'S. rega at 390x844 on the live build:
|
||||
// section.dms-pane has clientHeight 712 and scrollHeight 12,373 with overflow-y:auto, while
|
||||
// the document does not scroll at all and there is NO .vtl-host element in the tree.
|
||||
// VerticalTabsLayout does render a BackToTopButton, but it binds the active .vtl-host, which
|
||||
// only exists for rows carrying an `element` — and this SPA passes :groups whose rows carry
|
||||
// none, mounting its own panes instead. So that button's target is null here and it renders
|
||||
// nothing: the layout's button is for layouts that host their own element rows, not for us.
|
||||
activePaneEl() { return this.paneEls[this.activeIndex] || null },
|
||||
// The active tab's "?" text, or null: only discovered (Experimental) tabs, and only when
|
||||
// experimentalHelp.js has an entry for that bundle in this locale (English fallback inside).
|
||||
activeHelp() {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
export const STRINGS = {
|
||||
en: {
|
||||
backToTop: 'Back to top',
|
||||
'sec.dashboards': 'Dashboards', 'sec.prayer': 'Prayer Mobilization', 'sec.gospel': 'Gospel Research', 'sec.experimental': 'Experimental',
|
||||
'tab.dashboard-plus-grid': 'Big Picture', 'sub.dashboard-plus-grid': 'dashboard + people-groups grid, stacked',
|
||||
'tab.research-map': 'Research Map', 'sub.research-map': 'prayer · engagement · regions',
|
||||
|
|
@ -37,6 +38,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} only supports desktop — open this page on a desktop to use it.'
|
||||
},
|
||||
es: {
|
||||
backToTop: 'Volver arriba',
|
||||
'sec.dashboards': 'Paneles', 'sec.prayer': 'Movilización de oración', 'sec.gospel': 'Investigación del Evangelio', 'sec.experimental': 'Experimental',
|
||||
'tab.dashboard-plus-grid': 'Panorama general', 'sub.dashboard-plus-grid': 'panel + cuadrícula de pueblos',
|
||||
'tab.research-map': 'Mapa de investigación', 'sub.research-map': 'oración · compromiso · regiones',
|
||||
|
|
@ -58,6 +60,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} solo funciona en escritorio: abra esta página en un ordenador para usarlo.'
|
||||
},
|
||||
fr: {
|
||||
backToTop: 'Retour en haut',
|
||||
'sec.dashboards': 'Tableaux de bord', 'sec.prayer': 'Mobilisation à la prière', 'sec.gospel': "Recherche sur l'Évangile", 'sec.experimental': 'Expérimental',
|
||||
'tab.dashboard-plus-grid': "Vue d'ensemble", 'sub.dashboard-plus-grid': 'tableau de bord + grille des peuples',
|
||||
'tab.research-map': 'Carte de recherche', 'sub.research-map': 'prière · engagement · régions',
|
||||
|
|
@ -79,6 +82,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} ne fonctionne que sur ordinateur : ouvrez cette page sur un ordinateur pour l’utiliser.'
|
||||
},
|
||||
de: {
|
||||
backToTop: 'Nach oben',
|
||||
'sec.dashboards': 'Dashboards', 'sec.prayer': 'Gebetsmobilisierung', 'sec.gospel': 'Evangeliumsforschung', 'sec.experimental': 'Experimentell',
|
||||
'tab.dashboard-plus-grid': 'Gesamtbild', 'sub.dashboard-plus-grid': 'Dashboard + Raster der Volksgruppen',
|
||||
'tab.research-map': 'Forschungskarte', 'sub.research-map': 'Gebet · Engagement · Regionen',
|
||||
|
|
@ -100,6 +104,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} funktioniert nur am Desktop – öffnen Sie diese Seite an einem Computer.'
|
||||
},
|
||||
pt: {
|
||||
backToTop: 'Voltar ao topo',
|
||||
'sec.dashboards': 'Painéis', 'sec.prayer': 'Mobilização de oração', 'sec.gospel': 'Pesquisa do Evangelho', 'sec.experimental': 'Experimental',
|
||||
'tab.dashboard-plus-grid': 'Visão geral', 'sub.dashboard-plus-grid': 'painel + grade de povos',
|
||||
'tab.research-map': 'Mapa de pesquisa', 'sub.research-map': 'oração · engajamento · regiões',
|
||||
|
|
@ -121,6 +126,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} só funciona no computador — abra esta página num computador para usá-lo.'
|
||||
},
|
||||
it: {
|
||||
backToTop: 'Torna su',
|
||||
'sec.dashboards': 'Dashboard', 'sec.prayer': 'Mobilitazione alla preghiera', 'sec.gospel': 'Ricerca sul Vangelo', 'sec.experimental': 'Sperimentale',
|
||||
'tab.dashboard-plus-grid': "Quadro d'insieme", 'sub.dashboard-plus-grid': 'dashboard + griglia dei popoli',
|
||||
'tab.research-map': 'Mappa di ricerca', 'sub.research-map': 'preghiera · impegno · regioni',
|
||||
|
|
@ -144,6 +150,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} funziona solo su desktop: apri questa pagina da un computer per usarlo.'
|
||||
},
|
||||
ro: {
|
||||
backToTop: 'Sus',
|
||||
'sec.dashboards': 'Panouri', 'sec.prayer': 'Mobilizare la rugăciune', 'sec.gospel': 'Cercetarea Evangheliei', 'sec.experimental': 'Experimental',
|
||||
'tab.dashboard-plus-grid': 'Imaginea de ansamblu', 'sub.dashboard-plus-grid': 'panou + grila popoarelor',
|
||||
'tab.research-map': 'Hartă de cercetare', 'sub.research-map': 'rugăciune · implicare · regiuni',
|
||||
|
|
@ -165,6 +172,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} funcționează doar pe desktop — deschideți pagina pe un computer pentru a-l folosi.'
|
||||
},
|
||||
ru: {
|
||||
backToTop: 'Наверх',
|
||||
'sec.dashboards': 'Панели', 'sec.prayer': 'Молитвенная мобилизация', 'sec.gospel': 'Исследование Евангелия', 'sec.experimental': 'Экспериментальное',
|
||||
'tab.dashboard-plus-grid': 'Общая картина', 'sub.dashboard-plus-grid': 'панель + таблица народов',
|
||||
'tab.research-map': 'Исследовательская карта', 'sub.research-map': 'молитва · вовлечённость · регионы',
|
||||
|
|
@ -186,6 +194,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} работает только на компьютере — откройте эту страницу на компьютере.'
|
||||
},
|
||||
ar: {
|
||||
backToTop: 'إلى الأعلى',
|
||||
'sec.dashboards': 'لوحات المعلومات', 'sec.prayer': 'التعبئة للصلاة', 'sec.gospel': 'أبحاث الإنجيل', 'sec.experimental': 'تجريبي',
|
||||
'tab.dashboard-plus-grid': 'الصورة الكاملة', 'sub.dashboard-plus-grid': 'لوحة معلومات + شبكة الشعوب',
|
||||
'tab.research-map': 'خريطة البحث', 'sub.research-map': 'الصلاة · الانخراط · المناطق',
|
||||
|
|
@ -207,6 +216,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} يعمل على الحاسوب فقط — افتح هذه الصفحة على حاسوب لاستخدامه.'
|
||||
},
|
||||
hi: {
|
||||
backToTop: 'ऊपर जाएँ',
|
||||
'sec.dashboards': 'डैशबोर्ड', 'sec.prayer': 'प्रार्थना संचालन', 'sec.gospel': 'सुसमाचार शोध', 'sec.experimental': 'प्रायोगिक',
|
||||
'tab.dashboard-plus-grid': 'संपूर्ण चित्र', 'sub.dashboard-plus-grid': 'डैशबोर्ड + जनसमूहों की ग्रिड',
|
||||
'tab.research-map': 'शोध मानचित्र', 'sub.research-map': 'प्रार्थना · सहभागिता · क्षेत्र',
|
||||
|
|
@ -228,6 +238,7 @@ export const STRINGS = {
|
|||
desktopNotice: '{label} केवल डेस्कटॉप पर चलता है — इसे इस्तेमाल करने के लिए यह पेज कंप्यूटर पर खोलें।'
|
||||
},
|
||||
zh: {
|
||||
backToTop: '回到顶部',
|
||||
'sec.dashboards': '仪表板', 'sec.prayer': '祷告动员', 'sec.gospel': '福音研究', 'sec.experimental': '实验性',
|
||||
'tab.dashboard-plus-grid': '全景', 'sub.dashboard-plus-grid': '仪表板 + 民族网格',
|
||||
'tab.research-map': '研究地图', 'sub.research-map': '祷告 · 参与 · 区域',
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-country-map> custom element. -->
|
||||
<script src="../country-map.js" integrity="sha384-UePnW82iVOZHcCg4wPRwMLdgg115+FQCcgbba47udKD88uUBg+WzQyaLMf6No4m7" crossorigin="anonymous"></script>
|
||||
<script src="../country-map.js" integrity="sha384-wy2heDysPtrtI3kn0iBWER4cE7f42BaZg/C/qtz+9ktf21T55e1Hxm5XFe386PL2" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
|
||||
<script src="../../doxa-maps-spa.js" integrity="sha384-8FQdrGtOFVgucJU8TMFyU1ROZSGruK8ELNuDfQQEq4s+5UVS1RF2QflJWhbzOoXs" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-maps-spa.js" integrity="sha384-QWThl7hyaGP8Z4DloQ38XzH3QvDABHEBYI5AeTSv05bflD5kOKPcHDB/vhfch7no" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
|
||||
<script src="../doxa-maps-spa.js" integrity="sha384-8FQdrGtOFVgucJU8TMFyU1ROZSGruK8ELNuDfQQEq4s+5UVS1RF2QflJWhbzOoXs" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-maps-spa.js" integrity="sha384-QWThl7hyaGP8Z4DloQ38XzH3QvDABHEBYI5AeTSv05bflD5kOKPcHDB/vhfch7no" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
Loading…
Reference in a new issue