Show zone, go to the map, come back: the same card shows the zone again

PosterWall remembered the card it had shown, so after Show zone -> Map -> back the same press toggled the
selection off instead of showing it (rega row 79; UPG-100 and country-posters share the shape). The wall
now forgets its last-shown card when its pane goes inactive: it watches its ancestor chain, through shadow
roots, for the inert / hidden / aria-hidden a composite puts on an inactive view (the PinHint contract).
dx-shepherd ruled option (a). Needs eyes: rega row 79 plus the same arm on country-posters.
This commit is contained in:
Doxa Maps 2026-09-27 06:20:41 +00:00
parent 199cc61a19
commit 67e9ede550

View file

@ -39,7 +39,7 @@
* CROSS-PANE COMMS — this wall NEVER imports a map. It dispatches a window * CROSS-PANE COMMS — this wall NEVER imports a map. It dispatches a window
* CustomEvent scoped by instanceId, so several embeds on one page never cross-talk. * CustomEvent scoped by instanceId, so several embeds on one page never cross-talk.
*/ */
import { computed, ref, watch, onBeforeUnmount } from 'vue' import { computed, ref, watch, onBeforeUnmount, onMounted } from 'vue'
import { tStatic } from '../../i18n/index.js' import { tStatic } from '../../i18n/index.js'
// This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside // This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
@ -284,6 +284,24 @@ const toggleSection = (name) => {
const lastShown = ref(null) const lastShown = ref(null)
const missing = ref({}) const missing = ref({})
// FORGET the shown card when the wall's view goes inactive (dx-shepherd, row 79). A composite marks its
// inactive pane `inert` (the PinHint contract); after "Show zone" -> Map -> back, the same card must SHOW
// again, not toggle off a selection the reader can no longer see. Watches the ancestor chain, through
// shadow roots, for inert/hidden/aria-hidden; clears lastShown only (the map keeps its selection).
const wallEl = ref(null)
let paneMOs = []
onMounted(() => {
const chain = []
for (let n = wallEl.value; n; n = n.parentNode || n.host || null) if (n.nodeType === 1) chain.push(n)
const inactive = () => chain.some((a) => a.hasAttribute('inert') || a.hasAttribute('hidden') || a.getAttribute('aria-hidden') === 'true')
if (typeof MutationObserver === 'undefined') return
for (const a of chain) {
const mo = new MutationObserver(() => { if (inactive()) lastShown.value = null })
mo.observe(a, { attributes: true, attributeFilter: ['inert', 'hidden', 'aria-hidden'] })
paneMOs.push(mo)
}
})
onBeforeUnmount(() => { for (const mo of paneMOs) mo.disconnect(); paneMOs = [] })
function showOnMap(item) { function showOnMap(item) {
// TOGGLE, not a one-way set: a control the user can turn on but not off reads as // TOGGLE, not a one-way set: a control the user can turn on but not off reads as
@ -949,7 +967,7 @@ useShadowStyles(
</script> </script>
<template> <template>
<div class="wall" :class="{ 'is-dark': isDark, 'wall--embedded': embedded }"> <div ref="wallEl" class="wall" :class="{ 'is-dark': isDark, 'wall--embedded': embedded }">
<h2 class="wall-h">{{ heading }}</h2> <h2 class="wall-h">{{ heading }}</h2>
<div v-if="tag" class="wall-tag">{{ tag }}</div> <div v-if="tag" class="wall-tag">{{ tag }}</div>
<p v-if="intro" class="wall-sub" v-html="intro"></p> <p v-if="intro" class="wall-sub" v-html="intro"></p>