The centered set's legend covered the chart before anyone asked for it

A4.3. GiMap and GiTree already default their legends closed and read the host's
`legend: 'open'` knob; the centered set hardcoded ref(true), so it was the one
view whose decoder sat over the drawing from the first frame — on the chart where
seeing the target matters most. That was an inconsistency, not a considered
difference.

Changing the ref alone would have shipped NOTHING: applyWidth ran on mount and
set legendOpen back to `!m.matches`, so at any desktop width it reopened
immediately. The bug was in the width rule, not the initial value. Width now only
ever CLOSES the legend — a wide window is not a request to cover the chart, it is
just the absence of the reason to force it shut — and a choice the reader has
made still wins outright.

Checked as a state machine over the cases that matter: desktop with no host knob
closed, desktop with legend:'open' open, phone closed, phone→desktop stays
closed, and a reader who opens it keeps it through a rotation and a resize.
This commit is contained in:
Doxa Maps 2026-09-29 03:49:54 +00:00
parent ea610ce691
commit 98fd04c86d

View file

@ -40,7 +40,13 @@ const activeRing = ref(null)
// see the target and got a glossary. So below the breakpoint the legend starts CLOSED behind a
// toggle. It is not hidden: the control names it, and opening is one tap.
const narrow = ref(false)
const legendOpen = ref(true)
// ★ STARTS CLOSED, LIKE THE MAP'S AND THE TREE'S. This was `ref(true)`, so the centered set was the
// one view whose decoder covered the drawing before the reader had asked for it — and on the chart
// where seeing the target matters most. GiMap and GiTree already read the same profile-config knob
// (`legend: 'open'`) and default closed, so this was the odd one out rather than a considered
// difference. A host that wants it open says so; the reader opens it with one tap; and `chosen`
// below still protects whichever they pick from being undone by a resize.
const legendOpen = ref(board.profileConfig.value?.legend === 'open')
let mq = null
// ★ A DELIBERATE CHOICE SURVIVES A RESIZE. The first version of this set legendOpen from the
// breakpoint on EVERY width change, so a reader who opened the decoder on a phone lost it on
@ -52,7 +58,14 @@ let mq = null
let chosen = null // null = the reader has not decided yet
function applyWidth(m) {
narrow.value = m.matches
legendOpen.value = chosen == null ? !m.matches : chosen
// ★ WIDTH NO LONGER OPENS THE LEGEND, IT ONLY CLOSES IT. This read `!m.matches`, so on mount at a
// desktop width it set legendOpen back to TRUE and the closed default above was dead on arrival —
// changing the ref alone would have looked right in review and shipped nothing. A wide window is
// not a request to cover the chart; it is only the absence of the reason to force the legend shut.
// So: narrow still closes it, wide leaves whatever the default or the host asked for, and `chosen`
// still wins outright once the reader has decided.
if (chosen != null) { legendOpen.value = chosen; return }
if (m.matches) legendOpen.value = false
}
function setLegendOpen(v) { chosen = v; legendOpen.value = v }
onMounted(() => {