Merge gospel/board768 for the handoff (superseded; development's side kept)

# Conflicts:
#	plugin-designs/gospel-internet/src/components/GiBoundedSetMap.vue
#	plugin-designs/gospel-internet/src/components/GiCenteredSetMap.vue
#	plugin-designs/gospel-internet/src/setChartFeatures.js
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/gospel-internet/board/board/index.html
#	public/dx-maps/gospel-internet/board/index.html
#	public/dx-maps/gospel-internet/board/india-china/index.html
#	public/dx-maps/gospel-internet/board/language-tree/index.html
#	public/dx-maps/gospel-internet/board/platforms/index.html
#	public/dx-maps/gospel-internet/board/project-700/index.html
#	public/dx-maps/gospel-internet/board/zero/index.html
#	public/dx-maps/gospel-internet/gospel-internet.js
#	public/dx-maps/manifest.json
This commit is contained in:
Doxa Maps 2026-09-29 14:50:21 +00:00
commit 59345a0aaa
3 changed files with 26 additions and 3 deletions

View file

@ -39,6 +39,7 @@ import GiDrawer from './src/components/GiDrawer.vue'
import GiTree from './src/components/GiTree.vue'
import GiResources from './src/components/GiResources.vue'
import GiCombos from './src/components/GiCombos.vue'
import { isNarrowWidth } from './src/breakpoints.js'
const T = useGiT()
const board = useBoard()
@ -76,7 +77,7 @@ board.readUrl()
// partner's address bar is never rewritten. facetKeys is explicit: its default reads nothing on a cold load.
useShareableView(bus, { mode: 'query', write: board.profileConfig.value?.urlState === 'query', facetKeys: SHARE_FACETS })
// ── responsive: one panel at a time under 760px (ResizeObserver on the shell, not @container: a
// ── responsive: one panel at a time under the shared breakpoint (ResizeObserver on the shell, not @container: a
// container query cannot target the container itself, which is unreliable inside a shadow root) ──────
const shell = ref(null)
const isNarrow = ref(false)
@ -84,7 +85,7 @@ const mobilePanel = ref('map')
let ro = null
onMounted(() => {
if (shell.value && typeof ResizeObserver !== 'undefined') {
ro = new ResizeObserver(([e]) => { isNarrow.value = e.contentRect.width < 760 })
ro = new ResizeObserver(([e]) => { isNarrow.value = isNarrowWidth(e.contentRect.width) })
ro.observe(shell.value)
}
board.load()

View file

@ -0,0 +1,18 @@
/**
* breakpoints.js — the one width at which this dashboard stops being a three-column board.
*
* ★ IT IS A CONSTANT BECAUSE IT WAS TWO NUMBERS. board.vue collapsed to a single panel below
* 760px; the set charts stacked their legend below 900px. Between those two widths the board
* still held three columns while a chart inside it had already given up on having room — at
* 768 the centre column was about 145px, so the bounded figure was crushed to 124px and the
* centered figure's own minimum made it spill UNDER the right-hand panel.
*
* Neither number was wrong on its own. The defect was that they were separate, and nothing
* connected the width at which a chart needs room to the width at which the board gives it any.
*/
export const NARROW_MAX = 900
/** True when the shell is too narrow for side panels beside the centre column. */
export function isNarrowWidth(px) {
return Number(px) < NARROW_MAX
}

View file

@ -28,6 +28,7 @@ import { layoutCenteredSet, ringTally, inwardArrow, ringRadii } from '@map/compo
import GiRingLegend from './GiRingLegend.vue'
import GiCenteredSetMap from './GiCenteredSetMap.vue'
import FullscreenButton from '@map/components/map-controls/FullscreenButton.vue'
import { NARROW_MAX } from '../breakpoints.js'
const T = useGiT()
const board = useBoardState()
@ -70,7 +71,10 @@ function applyWidth(m) {
function setLegendOpen(v) { chosen = v; legendOpen.value = v }
onMounted(() => {
try {
mq = window.matchMedia('(max-width: 900px)')
// The same width the BOARD collapses at (NARROW_MAX). If these two ever disagree again,
// the board keeps its side panels while the chart has already given up on room — which is
// exactly the 768px failure.
mq = window.matchMedia(`(max-width: ${NARROW_MAX - 1}px)`)
applyWidth(mq)
mq.addEventListener?.('change', applyWidth)
} catch (_) { /* no matchMedia: stay wide, which is the layout that always fits */ }