From b1e839a33fc919dc8adc3b1f4ae1b867a3bed44b Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 18:14:57 +0000 Subject: [PATCH] Parameterize the grid for the merge, and correct what the merge actually is MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measuring the two grids changed the shape of this. The ruling reads as porting the regions dashboard's filters control into this one; the control is already here. Same class, same show/hide labels, same aria-expanded, same caret. What differs is the styling: this one is a bordered pill with a hover fill and a COUNT BADGE of active filters, the regions one is borderless text whose caret turns over on open. So the prop is filtersToggle — which toggle, not whether — and 'link' keeps the count badge. The Driver asked for the look of the control; removing a feature along with the border would not be a restyle. The backdrop is the same story. Both sides already use assets/images/worldmap.svg; this one scopes it to the filters block, the regions dashboard puts it on the list root at 60% / top / 400px floor, measured off their live page. So backdrop is a placement prop, and 'root' switches the filters copy OFF — the same artwork painted twice at two sizes reads as a rendering fault rather than a design. Both defaults reproduce today's grid exactly, so the three hosts that already ship it are unchanged until each opts in. C3 measured before building, as asked: nil. This grid declares no scroll container and no viewport-height unit, and neither does the regions list it replaces, so embedding it inside .rd-scroll cannot produce a scroller inside a scroller. One defect caught in passing: my first attempt redeclared filtersExpanded, which already exists. The parse gate named the line, and the duplicate was the thing that revealed the control was already there. --- .../people-groups-grid/people-groups-grid.vue | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/plugin-designs/people-groups-grid/people-groups-grid.vue b/plugin-designs/people-groups-grid/people-groups-grid.vue index c0fd6b6f9..52d21072a 100644 --- a/plugin-designs/people-groups-grid/people-groups-grid.vue +++ b/plugin-designs/people-groups-grid/people-groups-grid.vue @@ -72,6 +72,25 @@ defineOptions({ inheritAttrs: false }) const props = defineProps({ // ── injected standalone deps (replace Nuxt useRuntimeConfig / useI18n / useLocalePath) ── profileConfig: { type: String, default: '' }, + // ── the merge props (Driver 2026-09-28: one parameterized grid) ────────────────────────────── + // Both defaults reproduce TODAY's grid exactly, so every existing host is unchanged until it + // opts in. That is deliberate: this component already ships in three places and a merge that + // moved any of them without being asked would be the drift the merge exists to remove. + // + // filtersToggle: WHICH TOGGLE, not whether. Measuring the two grids turned up that this one + // ALREADY has the show/hide control — same class, same labels, same aria-expanded, same caret — + // so the ruling's "keep the regions filters control" is a RESTYLE, not a capability to port. + // 'button' = today: a bordered pill with a hover fill and a COUNT BADGE of active filters. + // 'link' = the regions dashboard's: borderless text with a caret that rotates 180 on open. + // The count badge exists only on 'button'. Losing it would be a real regression, so 'link' keeps + // it rather than reproducing the regions markup exactly — the Driver asked for the look of the + // control, not for a feature to be removed with it. + filtersToggle: { type: String, default: 'button' }, + // backdrop: where worldmap.svg goes. 'filters' = today (behind the filters block, and only when + // search or filters are on). 'root' = the regions treatment, measured off dx-life's live page: + // the LIST ROOT at background-size 60%, background-position top, min-height 400px. 'none' = off. + // Same asset either way — assets/images/worldmap.svg — so this is placement, not a second copy. + backdrop: { type: String, default: 'filters' }, prayBaseUrl: { type: String, default: '' }, languageCode: { type: String, default: '' }, // ★ default '' NOT '/research/': a non-empty prop default is ALWAYS truthy, so the computed @@ -237,6 +256,9 @@ const cfg = computed(() => { // Only drawn when the block actually exists: with show-search and show-filters both off there is // no filter block to sit behind, and a backdrop with nothing on it is just noise. const filtersBackdrop = computed(() => { + // 'root' takes the watermark over, so the filters block must NOT also paint it: two copies of + // the same artwork at different sizes reads as a rendering fault, not a design. + if (backdropMode.value !== 'filters') return null if (!useSearch.value && !useFilters.value) return null const base = resolveAssetsBase(cfg.value) return { @@ -326,6 +348,25 @@ const t = computed(() => { // ── Cat-2 show/hide (accept the DOM-attribute string 'false') ────────────────── const truthy = (v) => !(v === false || v === 'false' || v === '0' || v === 0) +const toggleStyle = computed(() => (props.filtersToggle === 'link' ? 'link' : 'button')) +const backdropMode = computed(() => (['filters', 'root', 'none'].includes(props.backdrop) ? props.backdrop : 'filters')) +/** + * The root treatment, measured off dx-life's live /regions page rather than invented: the LIST + * ROOT carries worldmap.svg at background-size 60%, background-position top, no-repeat, with a + * 400px floor so the watermark has room to read on a short list. Same asset the 'filters' mode + * uses — this is placement, not a second copy. + */ +const rootBackdrop = computed(() => { + if (backdropMode.value !== 'root') return null + const base = resolveAssetsBase(cfg.value) + return { + backgroundImage: `url(${base}/images/worldmap.svg)`, + backgroundSize: '60%', + backgroundPosition: 'top', + backgroundRepeat: 'no-repeat', + minHeight: '400px', + } +}) const useSearch = computed(() => truthy(props.showSearch)) const useFilters = computed(() => truthy(props.showFilters)) const useTotal = computed(() => truthy(props.showTotal)) @@ -894,7 +935,7 @@ onMounted(() => {