An Experimental map has a "?" that says what it is for and how to use it
The button shows only on a discovered tab with an entry in experimentalHelp.js. It opens a modal dialog titled with the tab name: focus moves to Close, Tab stays inside, Escape or Close returns focus to the button, and switching tab closes it. close is a new shell string in all 11 locales.
This commit is contained in:
parent
d8364d949a
commit
addf520dbe
2 changed files with 53 additions and 11 deletions
|
|
@ -151,6 +151,23 @@
|
|||
nothing switched, not to block the app. Sibling of the panes, not inside one, so it survives
|
||||
whichever tab is currently active. -->
|
||||
<div v-if="disabledNotice" class="dms-notice" role="status">{{ disabledNotice }}</div>
|
||||
|
||||
<!-- THE EXPERIMENTAL "?" — what a shelf map is for and how to use it (src/experimentalHelp.js).
|
||||
Shown only on a discovered tab that HAS an entry: a map with no text shows no button rather
|
||||
than an empty dialog. Modal: focus moves to Close, Tab stays inside, Escape or Close returns
|
||||
focus to the "?", and switching tab closes it. -->
|
||||
<button v-if="activeHelp" ref="helpBtn" type="button" class="dms-help-btn"
|
||||
:aria-label="tr('help')" :title="tr('help')" @click="openHelp">?</button>
|
||||
<div v-if="helpOpen && activeHelp" class="dms-help-scrim" @click.self="closeHelp"
|
||||
@keydown.esc.stop.prevent="closeHelp">
|
||||
<div class="dms-help" role="dialog" aria-modal="true" aria-labelledby="dms-help-title"
|
||||
@keydown.tab.prevent="$refs.helpClose && $refs.helpClose.focus()">
|
||||
<h2 id="dms-help-title" class="dms-help-title">{{ tabLabel(tabs[activeIndex]) }}</h2>
|
||||
<p class="dms-help-what"><strong>{{ activeHelp.what }}</strong></p>
|
||||
<p class="dms-help-how">{{ activeHelp.how }}</p>
|
||||
<button ref="helpClose" type="button" class="dms-help-close" @click="closeHelp">{{ tr('close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</VerticalTabsLayout>
|
||||
</template>
|
||||
|
||||
|
|
@ -159,6 +176,7 @@ import { defineComponent, inject } from 'vue'
|
|||
import VerticalTabsLayout from '@map/layouts/VerticalTabsLayout.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'
|
||||
import { loadScriptOnce, whenTagDefined } from '@map/utils/embedScript.js'
|
||||
|
||||
// THE HOST PAGE'S LANGUAGE, by the same ladder every nested map already uses (library/i18n
|
||||
|
|
@ -764,6 +782,7 @@ export default defineComponent({
|
|||
// onSelect's intercept). '' renders nothing; _noticeTimer clears any earlier message's timeout
|
||||
// so two quick clicks don't fight over when it disappears.
|
||||
disabledNotice: '', _noticeTimer: null,
|
||||
helpOpen: false,
|
||||
// Set when EVERY manifest candidate failed. The manifest carries each tab's scriptUrl, so
|
||||
// without it no src-composed tab can mount; this turns that into a visible pane message
|
||||
// instead of an empty grey rectangle. See loadManifest().
|
||||
|
|
@ -800,6 +819,12 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
// 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() {
|
||||
const t = this.tabs[this.activeIndex]
|
||||
return t && t.discovered ? helpFor(t.id, this.uiLocale) : null
|
||||
},
|
||||
// Merge profile-config (string or object) over the discrete props, so a host can pass either.
|
||||
cfg() {
|
||||
let pc = this.profileConfig
|
||||
|
|
@ -959,6 +984,7 @@ export default defineComponent({
|
|||
this._mql = null; this._onMedia = null
|
||||
},
|
||||
watch: {
|
||||
activeIndex() { this.helpOpen = false },
|
||||
// When the parent page changes the inherited `language` prop at runtime, re-drive the CURRENTLY
|
||||
// visible tab into the new language by re-setting its element's profile-config.locale (which is
|
||||
// languages.js's contract). Other tabs pick it up lazily on their next open, since mountElement
|
||||
|
|
@ -979,6 +1005,8 @@ export default defineComponent({
|
|||
tab(id) { if (id) this.onSelect(id) }
|
||||
},
|
||||
methods: {
|
||||
openHelp() { this.helpOpen = true; this.$nextTick(() => this.$refs.helpClose && this.$refs.helpClose.focus()) },
|
||||
closeHelp() { this.helpOpen = false; this.$nextTick(() => this.$refs.helpBtn && this.$refs.helpBtn.focus()) },
|
||||
setSlot(i, el) { if (el) this._slots = Object.assign(this._slots || {}, { [i]: el }) },
|
||||
// The gallery's own words in uiLocale (src/strings.js). `t` in the template is shadowed by the
|
||||
// v-for tab variable inside the panes, so those use `tr`; both are the same function.
|
||||
|
|
@ -1494,6 +1522,20 @@ export default defineComponent({
|
|||
|
||||
/* THE DEVICE-RULE NOTICE — the transient "desktop only" toast for the disabled Big Picture row on
|
||||
mobile. Material light only (surface/border/text/muted tokens), matching the rest of this file. */
|
||||
.dms-help-btn {
|
||||
position: fixed; right: 16px; bottom: 24px; z-index: 40; width: 36px; height: 36px; border-radius: 50%;
|
||||
font: 700 17px/1 Georgia, serif; color: #3b463d; background: #fff; border: 1px solid #d1d4cd;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,.12); cursor: pointer;
|
||||
}
|
||||
.dms-help-btn:focus-visible, .dms-help-close:focus-visible { outline: 2px solid #3f8f5a; outline-offset: 2px; }
|
||||
.dms-help-scrim { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.35); padding: 16px; }
|
||||
.dms-help {
|
||||
max-width: 420px; width: 100%; color: #3b463d; background: #fff; border-radius: 12px;
|
||||
padding: 18px 20px 14px; box-shadow: 0 12px 32px rgba(0,0,0,.2); font-size: 14px; line-height: 1.5;
|
||||
}
|
||||
.dms-help-title { margin: 0 0 8px; font-size: 16px; }
|
||||
.dms-help-what, .dms-help-how { margin: 0 0 10px; }
|
||||
.dms-help-close { float: right; font: inherit; padding: 6px 14px; border-radius: 8px; border: 1px solid #d1d4cd; background: #f3f3f1; cursor: pointer; }
|
||||
.dms-notice {
|
||||
position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 40;
|
||||
max-width: 320px; text-align: center; font-size: 13px; line-height: 1.4;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'UPG-100 List', 'sub.upg-100': 'my unreached list + posters',
|
||||
navLabel: 'Research maps', meta: '{n} maps', loading: 'Loading {label}…', loadFailed: 'Could not load {label}.',
|
||||
manifestHint: 'This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.',
|
||||
help: 'About this map', desktopOnly: 'desktop only', lab: 'lab', experimentalSub: 'experimental bundle',
|
||||
close: 'Close', help: 'About this map', desktopOnly: 'desktop only', lab: 'lab', experimentalSub: 'experimental bundle',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/en/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Toggle list", openViews: "Open the list of views", expandList: "Expand list", collapseList: "Collapse list", collapse: "Collapse",
|
||||
|
|
@ -47,7 +47,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Lista UPG-100', 'sub.upg-100': 'mi lista de no alcanzados + carteles',
|
||||
navLabel: 'Mapas de investigación', meta: '{n} mapas', loading: 'Cargando {label}…', loadFailed: 'No se pudo cargar {label}.',
|
||||
manifestHint: 'Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.',
|
||||
help: 'Acerca de este mapa', desktopOnly: 'solo escritorio', lab: 'beta', experimentalSub: 'mapa experimental',
|
||||
close: 'Cerrar', help: 'Acerca de este mapa', desktopOnly: 'solo escritorio', lab: 'beta', experimentalSub: 'mapa experimental',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/es/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Mostrar u ocultar la lista", openViews: "Abrir la lista de vistas", expandList: "Expandir la lista", collapseList: "Contraer la lista", collapse: "Contraer",
|
||||
|
|
@ -67,7 +67,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Liste UPG-100', 'sub.upg-100': 'ma liste des non atteints + affiches',
|
||||
navLabel: 'Cartes de recherche', meta: '{n} cartes', loading: 'Chargement de {label}…', loadFailed: 'Impossible de charger {label}.',
|
||||
manifestHint: "Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",
|
||||
help: 'À propos de cette carte', desktopOnly: 'ordinateur uniquement', lab: 'bêta', experimentalSub: 'carte expérimentale',
|
||||
close: 'Fermer', help: 'À propos de cette carte', desktopOnly: 'ordinateur uniquement', lab: 'bêta', experimentalSub: 'carte expérimentale',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/fr/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Afficher ou masquer la liste", openViews: "Ouvrir la liste des vues", expandList: "Déplier la liste", collapseList: "Replier la liste", collapse: "Replier",
|
||||
|
|
@ -87,7 +87,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'UPG-100-Liste', 'sub.upg-100': 'meine Liste der Unerreichten + Poster',
|
||||
navLabel: 'Forschungskarten', meta: '{n} Karten', loading: '{label} wird geladen…', loadFailed: '{label} konnte nicht geladen werden.',
|
||||
manifestHint: 'Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.',
|
||||
help: 'Über diese Karte', desktopOnly: 'nur Desktop', lab: 'Beta', experimentalSub: 'experimentelle Karte',
|
||||
close: 'Schließen', help: 'Über diese Karte', desktopOnly: 'nur Desktop', lab: 'Beta', experimentalSub: 'experimentelle Karte',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/de/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Liste ein-/ausblenden", openViews: "Ansichtsliste öffnen", expandList: "Liste ausklappen", collapseList: "Liste einklappen", collapse: "Einklappen",
|
||||
|
|
@ -107,7 +107,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Lista UPG-100', 'sub.upg-100': 'minha lista de não alcançados + cartazes',
|
||||
navLabel: 'Mapas de pesquisa', meta: '{n} mapas', loading: 'Carregando {label}…', loadFailed: 'Não foi possível carregar {label}.',
|
||||
manifestHint: 'Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.',
|
||||
help: 'Sobre este mapa', desktopOnly: 'só no computador', lab: 'beta', experimentalSub: 'mapa experimental',
|
||||
close: 'Fechar', help: 'Sobre este mapa', desktopOnly: 'só no computador', lab: 'beta', experimentalSub: 'mapa experimental',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/pt/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Mostrar ou ocultar a lista", openViews: "Abrir a lista de visualizações", expandList: "Expandir a lista", collapseList: "Recolher a lista", collapse: "Recolher",
|
||||
|
|
@ -129,7 +129,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Lista UPG-100', 'sub.upg-100': 'la mia lista dei non raggiunti + poster',
|
||||
navLabel: 'Mappe di ricerca', meta: '{n} mappe', loading: 'Caricamento di {label}…', loadFailed: 'Impossibile caricare {label}.',
|
||||
manifestHint: "Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",
|
||||
help: 'Informazioni su questa mappa', desktopOnly: 'solo desktop', lab: 'beta', experimentalSub: 'mappa sperimentale',
|
||||
close: 'Chiudi', help: 'Informazioni su questa mappa', desktopOnly: 'solo desktop', lab: 'beta', experimentalSub: 'mappa sperimentale',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/it/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Mostra o nascondi l’elenco", openViews: "Apri l’elenco delle viste", expandList: "Espandi l’elenco", collapseList: "Comprimi l’elenco", collapse: "Comprimi",
|
||||
|
|
@ -149,7 +149,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Lista UPG-100', 'sub.upg-100': 'lista mea de neatinși + afișe',
|
||||
navLabel: 'Hărți de cercetare', meta: '{n} hărți', loading: 'Se încarcă {label}…', loadFailed: '{label} nu a putut fi încărcat.',
|
||||
manifestHint: 'Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.',
|
||||
help: 'Despre această hartă', desktopOnly: 'doar pe desktop', lab: 'beta', experimentalSub: 'hartă experimentală',
|
||||
close: 'Închide', help: 'Despre această hartă', desktopOnly: 'doar pe desktop', lab: 'beta', experimentalSub: 'hartă experimentală',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/ro/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Afișează sau ascunde lista", openViews: "Deschide lista de vizualizări", expandList: "Extinde lista", collapseList: "Restrânge lista", collapse: "Restrânge",
|
||||
|
|
@ -169,7 +169,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'Список UPG-100', 'sub.upg-100': 'мой список недостигнутых + плакаты',
|
||||
navLabel: 'Исследовательские карты', meta: 'Карт: {n}', loading: 'Загрузка: {label}…', loadFailed: 'Не удалось загрузить: {label}.',
|
||||
manifestHint: 'Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.',
|
||||
help: 'Об этой карте', desktopOnly: 'только на компьютере', lab: 'бета', experimentalSub: 'экспериментальная карта',
|
||||
close: 'Закрыть', help: 'Об этой карте', desktopOnly: 'только на компьютере', lab: 'бета', experimentalSub: 'экспериментальная карта',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/ru/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "Показать или скрыть список", openViews: "Открыть список представлений", expandList: "Развернуть список", collapseList: "Свернуть список", collapse: "Свернуть",
|
||||
|
|
@ -189,7 +189,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'قائمة UPG-100', 'sub.upg-100': 'قائمتي لغير المُبشَّرين + ملصقات',
|
||||
navLabel: 'خرائط البحث', meta: 'عدد الخرائط: {n}', loading: 'جارٍ تحميل {label}…', loadFailed: 'تعذّر تحميل {label}.',
|
||||
manifestHint: 'تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.',
|
||||
help: 'عن هذه الخريطة', desktopOnly: 'على الحاسوب فقط', lab: 'تجريبي', experimentalSub: 'خريطة تجريبية',
|
||||
close: 'إغلاق', help: 'عن هذه الخريطة', desktopOnly: 'على الحاسوب فقط', lab: 'تجريبي', experimentalSub: 'خريطة تجريبية',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/ar/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "إظهار القائمة أو إخفاؤها", openViews: "فتح قائمة العروض", expandList: "توسيع القائمة", collapseList: "طي القائمة", collapse: "طي",
|
||||
|
|
@ -209,7 +209,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'UPG-100 सूची', 'sub.upg-100': 'मेरी अप्राप्त सूची + पोस्टर',
|
||||
navLabel: 'शोध मानचित्र', meta: '{n} मानचित्र', loading: '{label} लोड हो रहा है…', loadFailed: '{label} लोड नहीं हो सका।',
|
||||
manifestHint: 'यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।',
|
||||
help: 'इस नक्शे के बारे में', desktopOnly: 'केवल डेस्कटॉप', lab: 'बीटा', experimentalSub: 'प्रायोगिक मानचित्र',
|
||||
close: 'बंद करें', help: 'इस नक्शे के बारे में', desktopOnly: 'केवल डेस्कटॉप', lab: 'बीटा', experimentalSub: 'प्रायोगिक मानचित्र',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/hi/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "सूची दिखाएँ या छिपाएँ", openViews: "दृश्यों की सूची खोलें", expandList: "सूची फैलाएँ", collapseList: "सूची संक्षिप्त करें", collapse: "संक्षिप्त करें",
|
||||
|
|
@ -229,7 +229,7 @@ export const STRINGS = {
|
|||
'tab.upg-100': 'UPG-100 名单', 'sub.upg-100': '我的未得之民名单 + 海报',
|
||||
navLabel: '研究地图', meta: '{n} 张地图', loading: '正在加载{label}…', loadFailed: '无法加载{label}。',
|
||||
manifestHint: '此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。',
|
||||
help: '关于此地图', desktopOnly: '仅限桌面', lab: '测试版', experimentalSub: '实验性地图',
|
||||
close: '关闭', help: '关于此地图', desktopOnly: '仅限桌面', lab: '测试版', experimentalSub: '实验性地图',
|
||||
// The shared VerticalTabsLayout's own controls, VERBATIM from library/i18n/locales/zh/studio.json
|
||||
// (plugin studio's catalog) so both shells name the same buttons the same way.
|
||||
toggleList: "显示或隐藏列表", openViews: "打开视图列表", expandList: "展开列表", collapseList: "折叠列表", collapse: "折叠",
|
||||
|
|
|
|||
Loading…
Reference in a new issue