Phones: the search bar sits in its own header band; the share menu is titled Share and shows its content without scrolling
This commit is contained in:
parent
0bad29434d
commit
a025b69e14
6 changed files with 37 additions and 12 deletions
|
|
@ -218,7 +218,7 @@ useShadowStyles(`
|
|||
.dg-section-header-item { font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.6px;color:#9ca3af;padding:2px 0; }
|
||||
.dsm-dark .dg-section-header-item { color:rgba(243,243,241,0.45); }
|
||||
@media(max-width:767px){
|
||||
.mapboxgl-ctrl-top-left { top:10px!important;left:3px!important;right:3px!important;width:calc(100% - 6px)!important;max-width:none!important; }
|
||||
/* The phone search band (a header strip that holds the pill) is owned by GeocoderComponent. */
|
||||
/* Search-bar height (exactly 35px, desktop AND mobile) is now owned by the shared
|
||||
GeocoderComponent.vue injection 'geocoder-height-35' — no per-profile @media
|
||||
height hack needed (replaces bug-searchbar-mobile-height). */
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ useShadowStyles(`
|
|||
mobile) is now owned by the shared GeocoderComponent.vue injection
|
||||
'geocoder-height-35' — no per-profile @media height hack (replaces
|
||||
bug-searchbar-mobile-height). */
|
||||
.mapboxgl-ctrl-top-left { top:10px!important;left:3px!important;right:3px!important;width:calc(100% - 6px)!important;max-width:none!important; }
|
||||
/* The phone search band (a header strip that holds the pill) is owned by GeocoderComponent. */
|
||||
}
|
||||
|
||||
/* ── Dark mode: root class drives all child overrides ── */
|
||||
|
|
|
|||
|
|
@ -136,8 +136,14 @@ useShadowStyles(dualEngine(
|
|||
// MOBILE — go nearly edge-to-edge. Also shared: a phone has no room for a dead
|
||||
// side margin, and a profile that simply forgets this rule (as one did) silently
|
||||
// renders its DESKTOP width on mobile.
|
||||
+ '@media(max-width:767px){.mapboxgl-ctrl-top-left{top:10px!important;left:3px!important;'
|
||||
+ 'right:3px!important;width:calc(100% - 6px)!important;max-width:none!important;}}'
|
||||
// MOBILE — the band becomes a header strip across the top of the map that HOLDS the pill:
|
||||
// the strip spans the full width, its padding insets the pill, so the pill reads as sitting
|
||||
// IN a header rather than floating edge-to-edge. Desktop keeps the bare positioned slot.
|
||||
+ '@media(max-width:767px){.dg-search-band{top:0!important;left:0!important;right:0!important;'
|
||||
+ 'width:100%!important;max-width:none!important;margin:0!important;box-sizing:border-box!important;'
|
||||
+ 'padding:9px 14px!important;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,0.10);}'
|
||||
+ '.dg-search-band--dark{background:#3b463d;box-shadow:0 1px 4px rgba(0,0,0,0.35);}'
|
||||
+ '.dg-search-band .mapboxgl-ctrl,.dg-search-band .maplibregl-ctrl{margin:0!important;float:none!important;}}'
|
||||
// Light (default): rounded white pill + soft shadow.
|
||||
+ '.mapboxgl-ctrl-geocoder{border-radius:999px!important;background:#fff;'
|
||||
+ 'box-shadow:0 2px 8px rgba(0,0,0,0.15)!important;transition:box-shadow .12s,border-color .12s;}'
|
||||
|
|
@ -653,9 +659,23 @@ onMounted(async () => {
|
|||
}
|
||||
} else {
|
||||
map.addControl(geocoder.value, 'top-left')
|
||||
tagSearchBand()
|
||||
}
|
||||
})
|
||||
|
||||
// THE SEARCH BAND — the control container the engine creates for the 'top-left' slot is the
|
||||
// search bar's own row. Tagging it with a class of ours (instead of styling the engine's
|
||||
// .mapboxgl-ctrl-top-left directly) gives the band one owner and one name, so a profile never
|
||||
// has to know how the engine names its corners. On phones the band becomes a header strip that
|
||||
// holds the pill (see the 'geocoder-band' styles); on desktop it stays a bare positioned slot.
|
||||
function tagSearchBand() {
|
||||
const el = geocoder.value?.container?.parentElement
|
||||
if (!el) return
|
||||
el.classList.add('dg-search-band')
|
||||
el.classList.toggle('dg-search-band--dark', !!props.isDark)
|
||||
}
|
||||
watch(() => props.isDark, () => tagSearchBand())
|
||||
|
||||
// Mapbox Geocoder sets `placeholder` once at construction; it has no public
|
||||
// updater method. Watch the effective placeholder and patch the DOM input
|
||||
// directly so the per-map prop can change as the user switches profile tabs.
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
• It renders INSIDE the map area (teleported out of the toolbar into the same shadow
|
||||
root), so it never escapes the map's walls, never uses position:fixed, and scrolls
|
||||
with the map when the host page scrolls.
|
||||
• Its top edge is the toolbar's top edge and its max height is the toolbar column's
|
||||
height — every menu of a map shares the same band, whichever button opened it.
|
||||
• Its top edge is the toolbar's top edge. By default it is as tall as its content needs
|
||||
(bounded only by the map's bottom edge — no scrolling); `maxHeight` caps it lower and
|
||||
`matchToolbar` limits it to the toolbar column's height (content then scrolls).
|
||||
• It opens on the toolbar's inner side: to the LEFT of right-hand controls, to the
|
||||
RIGHT of left-hand controls. The side is measured, so a right-to-left page that
|
||||
mirrors the toolbar mirrors the menu as well.
|
||||
|
|
@ -18,8 +19,9 @@
|
|||
|
||||
Props: open (Boolean), title (String), isDark (Boolean),
|
||||
width (Number, 340) — preferred width; shrinks to what fits (mobile friendly)
|
||||
maxHeight (Number|null) — cap below the toolbar column's height (null = the column)
|
||||
height (Number|null) — a fixed height instead of fitting the content
|
||||
maxHeight (Number|null) — cap the height (null = fit the content within the map)
|
||||
height (Number|null) — a fixed height instead of fitting the content
|
||||
matchToolbar (Boolean) — limit the height to the toolbar column (content scrolls)
|
||||
Emits: close
|
||||
Slot: the menu content (tabs, buttons, text) — chrome (header, close) is provided here.
|
||||
-->
|
||||
|
|
@ -52,6 +54,7 @@ const props = defineProps({
|
|||
isDark: { type: Boolean, default: false },
|
||||
maxHeight: { type: Number, default: null },
|
||||
height: { type: Number, default: null },
|
||||
matchToolbar: { type: Boolean, default: false },
|
||||
})
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
|
|
@ -73,7 +76,8 @@ function place() {
|
|||
const offset = onRight ? (ar.right - tr.left + gap) : (tr.right - ar.left + gap)
|
||||
const width = Math.max(200, Math.min(props.width, ar.width - offset - edge))
|
||||
const top = Math.max(0, tr.top - ar.top)
|
||||
let maxHeight = Math.max(120, Math.min(tr.height, ar.height - top - edge))
|
||||
let maxHeight = Math.max(120, ar.height - top - edge) // fit the content inside the map
|
||||
if (props.matchToolbar) maxHeight = Math.max(120, Math.min(maxHeight, tr.height))
|
||||
if (props.maxHeight) maxHeight = Math.min(maxHeight, props.maxHeight)
|
||||
style.value = {
|
||||
top: `${Math.round(top)}px`,
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ async function copyEmbed() {
|
|||
ref="btnEl"
|
||||
:is-dark="isDark"
|
||||
:active="isOpen"
|
||||
:title="t('buttons.shareEmbed')"
|
||||
:title="t('buttons.share')"
|
||||
@click="toggle"
|
||||
>
|
||||
<!-- Share icon: box with upward arrow (iOS / Material standard) -->
|
||||
|
|
@ -441,7 +441,7 @@ async function copyEmbed() {
|
|||
</MapControlButton>
|
||||
|
||||
<!-- =================== Menu (shared MapControlMenu owns placement + chrome) =================== -->
|
||||
<MapControlMenu :open="isOpen" :title="t('buttons.shareEmbed')" :is-dark="isDark" @close="close">
|
||||
<MapControlMenu :open="isOpen" :title="t('buttons.share')" :is-dark="isDark" @close="close">
|
||||
<div ref="popoverEl" class="share-pop" :class="{ light: !isDark }">
|
||||
<!-- The multiplication path — one line each, top of the menu -->
|
||||
<ul class="share-steps">
|
||||
|
|
|
|||
|
|
@ -28,5 +28,6 @@
|
|||
"Train them to embed it too",
|
||||
"Train them to train others to embed it too",
|
||||
"Multiply maps everywhere for Jesus!"
|
||||
]
|
||||
],
|
||||
"share": "Share"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue