doxa-maps/library/components/map-controls/HelpButton.vue
Doxa Maps 457d16e708 A map's own ? can ask its host for help: HelpButton and useHostedHelp send doxa:help
The Experimental maps' explainer lived in a "?" floating at the top centre of the app, which read
as a game piece rather than part of the map. The map already has a "?" control. This lets that
control answer from the HOST: a click dispatches doxa:help, bubbling and composed, so it crosses
every shadow root between the button and the page, and the app answers with the map's text.

library/composables/useHostedHelp.js is the one mechanism, for the HelpButton map control and for
the maps whose "?" belongs in their own bar. It also decides WHERE the button shows: only under a
host that answers (an ancestor, across shadow roots, carrying data-doxa-help), so the same bundle
embedded on a partner page shows no dead "?". HelpButton keeps its open-help emit, so
doxa-simple-map's own help popup is unchanged; hosted is opt-in.
2026-09-29 02:35:35 +00:00

47 lines
1.7 KiB
Vue

<!--
HelpButton.vue — the map's "?" control: what this map is and how to use it.
One click, two ways to answer it:
- `open-help` (emit): the map shows its own help (doxa-simple-map's popup does).
- `doxa:help` (a DOM event, bubbling and COMPOSED; see composables/useHostedHelp.js): a HOST
answers for the map. The Doxa Maps app (doxa-maps-spa) answers with the Experimental shelf's
what/how text, which is how that explainer left the top of the screen for the map's own control
column, next to zoom and fullscreen.
Props:
isDark — theme flag forwarded from parent
hosted — show the button ONLY under a host that answers doxa:help. A map whose help lives in its
host sets this, so the same bundle embedded on a page with no such host shows no dead "?".
Emits:
open-help — fires on click; parent decides how to display help content
-->
<script setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import MapControlButton from './MapControlButton.vue'
import { useHostedHelp } from '../../composables/useHostedHelp.js'
const { t } = useI18n()
const props = defineProps({
isDark: { type: Boolean, default: false },
hosted: { type: Boolean, default: false }
})
const emit = defineEmits(['open-help'])
const { hosted: underHost, askForHelp } = useHostedHelp()
const shown = computed(() => !props.hosted || underHost.value)
function onClick() {
emit('open-help')
askForHelp()
}
</script>
<template>
<MapControlButton v-if="shown" data-control="help" :is-dark="isDark" :title="t('buttons.aboutThisMap')" @click="onClick">
<span style="font-size:15px;font-weight:700;font-family:serif;line-height:1;">?</span>
</MapControlButton>
</template>