Share menu paints above every map layer: the toolbar lifts while a menu is open; the menu stays inside the map's bottom edge; phone band spans the map
This commit is contained in:
parent
cb57fd6ed7
commit
a391cfb65e
2 changed files with 29 additions and 5 deletions
|
|
@ -40,6 +40,11 @@ useShadowStyles(`
|
|||
gap: var(--map-toolbar-gap, 8px);
|
||||
z-index: 10;
|
||||
}
|
||||
/* While a control's menu (the share menu) is open the toolbar is lifted above every other
|
||||
map layer — search pill, legend, sheet — so the menu can never underlap them. */
|
||||
.map-toolbar.has-open-menu {
|
||||
z-index: 3000;
|
||||
}
|
||||
/* Slim every toolbar control to a fixed 32px (coder 2026-06-24: "buttons can be
|
||||
smaller"): smaller but still tappable, and uniform so they all align. The icons
|
||||
inside stay their own fixed px sizes (they don't scale with the button), so they
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
- Re-click the share button
|
||||
-->
|
||||
<script setup>
|
||||
import { ref, computed, inject, unref, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { ref, computed, inject, unref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useShadowStyles } from '../../composables/useShadowStyles.js'
|
||||
import { resolveShareUrl } from '../../utils/embedBase.js'
|
||||
|
|
@ -58,7 +58,7 @@ useShadowStyles(`
|
|||
border-radius:12px;
|
||||
box-shadow:0 6px 24px rgba(0,0,0,0.45);
|
||||
padding:0;
|
||||
z-index:1100;
|
||||
z-index:3000;
|
||||
color:#e6edf3;
|
||||
font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
|
||||
font-size:13px;
|
||||
|
|
@ -368,9 +368,10 @@ useShadowStyles(`
|
|||
@media(max-width:767px){
|
||||
.share-pop{
|
||||
position:fixed;
|
||||
top:120px;
|
||||
top:64px;
|
||||
left:10px;
|
||||
right:52px;
|
||||
right:10px;
|
||||
z-index:3000;
|
||||
width:auto;
|
||||
max-width:none;
|
||||
max-height:calc(100vh - 96px);
|
||||
|
|
@ -389,7 +390,24 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
/* ---- state ---- */
|
||||
const rootEl = ref(null)
|
||||
const isOpen = ref(false)
|
||||
// The toolbar (this button's parent) is lifted above every map layer while the menu is open.
|
||||
watch(isOpen, async (open) => {
|
||||
const tb = rootEl.value?.closest('.map-toolbar'); if (tb) tb.classList.toggle('has-open-menu', open)
|
||||
if (open) { await nextTick(); keepInsideMap() }
|
||||
})
|
||||
// Natural placement: top-aligned with the button, to its left; if the menu would run past the
|
||||
// map's bottom edge it slides up just enough to stay inside (desktop only — phones use a band).
|
||||
const popShift = ref(0)
|
||||
function keepInsideMap() {
|
||||
const pop = rootEl.value?.querySelector('.share-pop'); const host = rootEl.value?.getRootNode()?.host
|
||||
if (!pop || !host || window.matchMedia('(max-width: 767px)').matches) { popShift.value = 0; return }
|
||||
popShift.value = 0
|
||||
const hb = host.getBoundingClientRect(), pr = pop.getBoundingClientRect()
|
||||
const overflow = pr.bottom - (hb.bottom - 8)
|
||||
if (overflow > 0) popShift.value = -Math.min(overflow, Math.max(0, pr.top - hb.top - 8))
|
||||
}
|
||||
const popoverEl = ref(null)
|
||||
const btnEl = ref(null)
|
||||
const activeTab = ref('link') // 'link' | 'embed'
|
||||
|
|
@ -511,7 +529,7 @@ onBeforeUnmount(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="share-wrap">
|
||||
<div ref="rootEl" class="share-wrap">
|
||||
<MapControlButton
|
||||
ref="btnEl"
|
||||
:is-dark="isDark"
|
||||
|
|
@ -536,6 +554,7 @@ onBeforeUnmount(() => {
|
|||
ref="popoverEl"
|
||||
class="share-pop"
|
||||
:class="{ light: !isDark }"
|
||||
:style="popShift ? { top: popShift + 'px' } : null"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div class="share-header">
|
||||
|
|
|
|||
Loading…
Reference in a new issue