Basemap follows the tab: prayer stays night, every other map is day in monochrome white
- useMapTheme: one look rule (any prayer strategy → night/default; everything else → day/monochrome) applied at boot and on every tab switch in the simple map and the research map; an unknown strategy keeps the current look - Legends and the research search pill are 380px again; desktop numeric columns 70px at 13px so every row stays on one line with no overlap - Map containers carry their map instance for gates (no global)
This commit is contained in:
parent
1ae532481f
commit
1b22fa419b
5 changed files with 40 additions and 16 deletions
|
|
@ -427,6 +427,10 @@ const showTabBar = computed(() => true)
|
|||
|
||||
const activeTabId = ref(null)
|
||||
const activeTab = computed(() => tabs.value.find(t => t.id === activeTabId.value) ?? tabs.value[0])
|
||||
// Basemap look follows the active tab: prayer → night, everything else → day (monochrome).
|
||||
// Re-evaluated whenever the tab changes, including when the tab list arrives after boot.
|
||||
mapTheme.setLook(mapTheme.lookFor(activeTab.value?.colorStrategy))
|
||||
watch(() => activeTab.value?.colorStrategy, (strategy) => mapTheme.setLook(mapTheme.lookFor(strategy), map.value))
|
||||
const activeLegendType = computed(() => activeTab.value?.legend ?? 'default')
|
||||
const activePopupAction = computed(() => activeTab.value?.popup ?? 'pray')
|
||||
|
||||
|
|
@ -1327,10 +1331,8 @@ function switchTab(tabId) {
|
|||
if (!FEATURES.geocoderPersistAcrossTabs) clearGeocoderProgrammatic()
|
||||
const tab = tabs.value.find(t => t.id === tabId)
|
||||
if (!tab || !map.value) return
|
||||
// Re-assert the persisted theme's basemap lightPreset/theme on EVERY tab switch — defensive
|
||||
// so dark mode can't appear "not working" on any tab (bug-dark-mode-multi-tab). Cheap: it's
|
||||
// a config prop (no setStyle).
|
||||
mapTheme.applyTheme(map.value)
|
||||
// The basemap look follows the tab (prayer → night, others → day); config prop only, no reload.
|
||||
mapTheme.setLook(mapTheme.lookFor(tab.colorStrategy), map.value)
|
||||
// Lazy-load regions GeoJSON the first time the user lands on this tab.
|
||||
if (tab.id === 'doxa-regions') void ensureRegionsLoaded()
|
||||
|
||||
|
|
@ -1929,7 +1931,7 @@ function applyContainerScale(width) {
|
|||
// cards). SemanticTreeLegend's .stl-panel follows this variable too.
|
||||
// 400px (was 380) since the desktop type scale widened the numeric
|
||||
// columns; keeps "Full Prayer Coverage" on one line (2026-09-16).
|
||||
el.style.setProperty('--map-legend-width', '400px')
|
||||
el.style.setProperty('--map-legend-width', '380px')
|
||||
} else if (width >= 500) {
|
||||
el.style.setProperty('--map-btn-size', '36px')
|
||||
el.style.setProperty('--map-toolbar-gap', '6px')
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ function applyContainerScale(width) {
|
|||
el.style.setProperty('--map-toolbar-gap', '8px')
|
||||
el.style.setProperty('--map-font-md', '13px')
|
||||
el.style.setProperty('--map-font-sm', '11px')
|
||||
el.style.setProperty('--map-legend-width', '400px')
|
||||
el.style.setProperty('--map-legend-width', '380px')
|
||||
} else if (width >= 500) {
|
||||
el.style.setProperty('--map-btn-size', '36px')
|
||||
el.style.setProperty('--map-toolbar-gap', '6px')
|
||||
|
|
@ -447,6 +447,10 @@ const mapStore = inject('mapStore')
|
|||
const dataStore = inject('dataStore')
|
||||
const uiStore = inject('uiStore')
|
||||
const mapTheme = useMapTheme(uiStore)
|
||||
// Basemap look follows the active tab: prayer → night, everything else → day (monochrome).
|
||||
// Re-evaluated whenever the tab changes, including when the tab list arrives after boot.
|
||||
mapTheme.setLook(mapTheme.lookFor(activeTab.value?.colorStrategy))
|
||||
watch(() => activeTab.value?.colorStrategy, (strategy) => mapTheme.setLook(mapTheme.lookFor(strategy), map.value))
|
||||
// loc-012: feed the active locale into the bulk/list data fetch so the data the
|
||||
// search bar searches comes back in the selected language — the same `lang` param
|
||||
// the people-group detail fetch uses (PeopleGroupDetail.vue). null → API default.
|
||||
|
|
@ -837,9 +841,8 @@ function switchTab(tabId) {
|
|||
activeTabId.value = tabId
|
||||
const tab = tabs.value.find(t => t.id === tabId)
|
||||
if (!tab || !map.value) return
|
||||
// Re-assert the persisted theme's basemap lightPreset on every tab switch (defensive,
|
||||
// config-prop only — keeps dark mode consistent across tabs). bug-dark-mode-multi-tab.
|
||||
mapTheme.applyTheme(map.value)
|
||||
// The basemap look follows the tab (prayer → night, others → day); config prop only, no reload.
|
||||
mapTheme.setLook(mapTheme.lookFor(tab.colorStrategy), map.value)
|
||||
const strategyKey = tab.colorStrategy
|
||||
const colorMode =
|
||||
strategyKey === 'engagement' ? COLOR_MODES.ENGAGEMENT :
|
||||
|
|
|
|||
|
|
@ -977,11 +977,11 @@ useShadowStyles(`
|
|||
.stl-panel:not(.legend-mobile-sheet *) .stl-hdr-name { font-size: 13px; }
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-hdr-num { font-size: 10px; }
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-name { font-size: 15px; }
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-num { font-size: 13.5px; }
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-num { font-size: 13px; }
|
||||
/* The numeric columns must grow with the type: "POPULATION" at 10px is ~65px, ~76px with
|
||||
its sort arrow; "139.0M" at 13.5px is ~49px. A fixed 44px column let the header collide
|
||||
with "UUPGs" and let values spill into the neighbouring column (Driver, 2026-09-16). */
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-inner { --stl-num-w: 76px; } /* the vars live on .stl-inner */
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-inner { --stl-num-w: 70px; } /* the vars live on .stl-inner */
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-hdr-num,
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-num { white-space: nowrap; }
|
||||
.stl-panel:not(.legend-mobile-sheet *) .stl-info-pop { font-size: 13px; }
|
||||
|
|
|
|||
|
|
@ -366,6 +366,8 @@ export function useMapInstance({
|
|||
attributionControl: true // Mapbox's own attribution on every map
|
||||
})
|
||||
claimLogo(map.value)
|
||||
// Probe hook: the container element carries its map so gates can read live config (no global).
|
||||
try { containerRef.value.__doxaMap = map.value } catch (_) {}
|
||||
} else {
|
||||
// Fragment config for THIS boot (a thunk re-reads the theme on every re-init).
|
||||
const initialConfig = typeof config === 'function' ? config() : config
|
||||
|
|
@ -394,6 +396,8 @@ export function useMapInstance({
|
|||
attributionControl: true // Mapbox's own attribution on every map
|
||||
})
|
||||
claimLogo(map.value)
|
||||
// Probe hook: the container element carries its map so gates can read live config (no global).
|
||||
try { containerRef.value.__doxaMap = map.value } catch (_) {}
|
||||
}
|
||||
|
||||
// Belt-and-suspenders to dragRotate:false — kills the two-finger twist→rotate
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ export const THEME_TOGGLE = false
|
|||
// The basemap look that is pinned when THEME_TOGGLE is false. These are the exact
|
||||
// values the ORIGINAL dark mode used, so the map is visually unchanged.
|
||||
export const FIXED_BASEMAP = { lightPreset: 'night', theme: 'default' }
|
||||
// The light look: the same Standard style lit by day in the monochrome (white) theme, so the
|
||||
// pins stand out on every map that informs rather than prays. Prayer maps keep the night look (light and darkness).
|
||||
export const LIGHT_BASEMAP = { lightPreset: 'day', theme: 'monochrome' }
|
||||
// Which look a colour strategy asks for: prayer → dark, everything else → light.
|
||||
// Unknown strategy (tabs not loaded yet) → null: the current look is kept.
|
||||
export function lookForStrategy(strategy) { return !strategy ? null : (/prayer/i.test(String(strategy)) ? 'dark' : 'light') } // 'prayer', 'prayerProgress', …
|
||||
|
||||
export function useMapTheme(uiStore) {
|
||||
// Single pending 'idle' re-assert guard (per map instance). Prevents stacking one
|
||||
|
|
@ -69,11 +75,20 @@ export function useMapTheme(uiStore) {
|
|||
// both the boot `config` (bootConfig) and every live re-pin (applyTheme), so the first
|
||||
// painted frame and a later re-assert can never disagree. Recomputed fresh on every call
|
||||
// (rapid toggles can't desync — last call wins).
|
||||
// The pinned look for this map instance: 'dark' (prayer) or 'light' (every other tab).
|
||||
// Set from the active tab's colour strategy at boot and on each tab switch (setLook).
|
||||
let look = 'dark'
|
||||
function lookFor(strategy) { return lookForStrategy(strategy) }
|
||||
function setLook(next, map) {
|
||||
if (next !== 'light' && next !== 'dark') return // unknown → keep the current look
|
||||
look = next
|
||||
if (map) applyTheme(map)
|
||||
}
|
||||
function basemapConfig() {
|
||||
// FLAG OFF → the basemap is PINNED to the dark/colourful look and does NOT follow the
|
||||
// UI theme. This is what lets the chrome be light while the map keeps its dark-green
|
||||
// colour strategy.
|
||||
if (!THEME_TOGGLE) return { ...FIXED_BASEMAP }
|
||||
// FLAG OFF → the basemap is PINNED per look and does NOT follow the UI theme. This is
|
||||
// what lets the chrome stay light while a prayer map keeps its dark-green look and an
|
||||
// informational map its day-lit green look.
|
||||
if (!THEME_TOGGLE) return { ...(look === 'light' ? LIGHT_BASEMAP : FIXED_BASEMAP) }
|
||||
const dark = isDarkTheme()
|
||||
// lightPreset = day/night lighting. theme = the Standard colour theme: light mode uses
|
||||
// the LIGHTER, cleaner 'monochrome' theme (closer to a flat white map); dark keeps the
|
||||
|
|
@ -189,5 +204,5 @@ export function useMapTheme(uiStore) {
|
|||
applyTheme(map)
|
||||
}
|
||||
|
||||
return { STANDARD_STYLE, LIGHT_STYLE, DARK_STYLE, isDarkTheme, lightPreset, basemapConfig, bootStyle, bootConfig, applyTheme, swapTheme }
|
||||
return { setLook, lookFor, STANDARD_STYLE, LIGHT_STYLE, DARK_STYLE, isDarkTheme, lightPreset, basemapConfig, bootStyle, bootConfig, applyTheme, swapTheme }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue