diff --git a/library/components/info/MapInfo.vue b/library/components/info/MapInfo.vue index f4e8c1fb1..954d55b80 100644 --- a/library/components/info/MapInfo.vue +++ b/library/components/info/MapInfo.vue @@ -65,6 +65,14 @@ const props = defineProps({ takeaway: { type: String, default: '' }, /** A caveat under the examples (e.g. which countries are not supported yet). Key or string. */ noteKey: { type: String, default: '' }, + /** + * The map's STRATEGY, as a catalogue key PREFIX (e.g. 'mapInfo.tab.upg-100.strategy'): .bottom is + * the bottom line, .p1, .p2 … the points, read in order until the first one that is missing. So + * the number of points is the catalogue's business, never a count kept here. With a strategy the popup + * shows the intro (the lead), then the strategy; a map that also has examples gets two tabs, EXAMPLES + * first. The takeaway is not shown beside a strategy, which supersedes it. + */ + strategyKey: { type: String, default: '' }, note: { type: String, default: '' }, /** The artefacts, in display order. See the header for the four kinds. */ examples: { type: Array, default: () => [] }, @@ -106,6 +114,25 @@ function lang() { } const t = useOptionalT('', { fallback: (q) => tStatic(q, lang()) }) const text = (key, str) => (key ? t(key) : str) +// The strategy, read from the catalogue in the reader's language (tStatic falls back to English per key). +// lang() reads `opens`, so the lines are re-read on every open. A point is a non-empty string; the first +// missing one ends the list. +const MAX_POINTS = 8 +const strategyBottom = () => (props.strategyKey ? tStatic(props.strategyKey + '.bottom', lang()) || '' : '') +function strategyPoints() { + const out = [] + if (!props.strategyKey) return out + for (let i = 1; i <= MAX_POINTS; i++) { + const v = tStatic(props.strategyKey + '.p' + i, lang()) + if (!v) break + out.push(v) + } + return out +} +const hasStrategy = () => !!strategyBottom() +// Two tabs only where there is something on both sides: examples AND a strategy. +const hasTabs = () => hasStrategy() && (props.examples || []).length > 0 +const view = ref('examples') const num = (n) => { try { return new Intl.NumberFormat(lang()).format(n) } catch { return String(n) } } const isRtl = () => lang() === 'ar' @@ -162,6 +189,7 @@ const failed = reactive({}) async function show() { opens.value++ open.value = true + view.value = 'examples' // A page-load pointer is done for this load once the popup has been opened (in memory only). if (pageLoad()) pointerDoneThisLoad.add(props.storageKey) await nextTick() @@ -415,6 +443,16 @@ useShadowStyles(` .mi-takeaway{ margin:0 0 14px; color:#3b4256; } .mi-takeaway b{ color:#1b1f2a; } .mi-ex{ margin:18px 0 0; } + .mi-tabs{ display:flex; gap:4px; margin:14px 0 0; border-bottom:1px solid #e6e8ee; } + .mi-tab{ min-height:44px; padding:0 16px; border:none; background:none; color:#3b4256; font:inherit; font-weight:600; + cursor:pointer; border-bottom:3px solid transparent; margin-bottom:-1px; } + .mi-tab[aria-selected="true"]{ color:#1b1f2a; border-bottom-color:#3b463d; } + .mi-tab:focus-visible{ outline:3px solid #2563eb; outline-offset:-3px; } + .mi-strategy{ margin:16px 0 0; } + .mi-strategy h3{ margin:0 0 6px; } + .mi-bottom{ margin:0 0 8px; font-weight:600; color:#1b1f2a; } + .mi-points{ margin:0; padding-inline-start:20px; } + .mi-points li{ margin:0 0 6px; } .mi-ex h3{ margin:0 0 8px; font-size:15px; text-transform:uppercase; letter-spacing:.04em; color:#556; } .mi-img{ display:block; width:100%; height:auto; border-radius:8px; background:#f4f5f8; box-shadow:0 1px 4px rgba(0,0,0,.15); } @@ -547,7 +585,22 @@ useShadowStyles(`

{{ text(leadKey, lead) }}

-

{{ t('mapInfo.takeaway') }} {{ text(takeawayKey, takeaway) }}

+

{{ t('mapInfo.takeaway') }} {{ text(takeawayKey, takeaway) }}

+ +
+ + +
+ +
+

{{ t('mapInfo.tabStrategy') }}

+

{{ strategyBottom() }}

+
    +
  • {{ p }}
  • +
+
+ + + +

{{ text(noteKey, note) }}

diff --git a/plugin-designs/doxa-simple-map/src/mapInfo.js b/plugin-designs/doxa-simple-map/src/mapInfo.js index 1aa52dd25..fb3f7a3d3 100644 --- a/plugin-designs/doxa-simple-map/src/mapInfo.js +++ b/plugin-designs/doxa-simple-map/src/mapInfo.js @@ -13,6 +13,7 @@ const PRAYER = { // The approximate-location caveat, kept here where a reader who asks will always find it, whether or not // the map shows its own pin note. The same catalogue string that note uses. noteKey: 'pins.approximate', + strategyKey: 'mapInfo.tab.prayer-map.strategy', examples: [], }