diff --git a/plugin-designs/research-dashboard/src/components/dashboards/DashboardChartsRail.vue b/plugin-designs/research-dashboard/src/components/dashboards/DashboardChartsRail.vue index 664b562f5..3c9da1eaf 100644 --- a/plugin-designs/research-dashboard/src/components/dashboards/DashboardChartsRail.vue +++ b/plugin-designs/research-dashboard/src/components/dashboards/DashboardChartsRail.vue @@ -6,11 +6,41 @@ * click via delegation on the stable container (per-element @click is unreliable in a virtualized/ * patched defineCustomElement tree). Tweens via CSS (bar width + slice opacity). */ -import { inject, computed } from 'vue' +import { inject, computed, ref } from 'vue' import { useShadowStyles } from '@map/composables/useShadowStyles.js' import { aggregate, buildDonut, buildBars, lbl, buildCountryRegionColors } from '../../composables/useDashboardAggregations.js' import { buildSearchAccessors, makeSearchMatcher } from '../../composables/useDashboardShell.js' +/** + * ── THE RAIL'S TAB STRIP ────────────────────────────────────────────────────────────────────── + * Charts is selected by default, which is the Driver's wording: "Charts will be a SELECTED TAB + * that will show the charts." + * + * ★ GOSPEL RESOURCES SHIPS DISABLED, NOT HIDDEN, and that is a deliberate choice rather than a + * placeholder. Its content is not a separate dataset panel — the Driver described it as the SAME + * facet breakdown re-measured on a different axis ("people groups by their gospel resources + * availability"), and three decisions about that data are still open: the official lostness number, + * whether to stay key-less or register a Joshua Project key, and the UI shape. Guessing any of them + * would ship a wrong picture that looks right, which is this codebase's most expensive failure mode. + * + * A HIDDEN tab is indistinguishable from an unbuilt one. A disabled tab carrying its reason in the + * title attribute tells the Driver exactly what it is waiting on, every time he looks at the rail — + * which is worth more than the tab being invisible until it is perfect. + * + * `tabs` is a plain array rather than config-driven on purpose: there are two of them and one is a + * stub. Making it configurable now would be an abstraction over a single real case. + */ +const tabs = [ + { id: 'charts', label: 'Charts' }, + { + id: 'gospel', + label: 'Gospel Resources', + disabled: true, + why: 'Waiting on three decisions: the official lostness number, key-less vs a registered Joshua Project key, and the UI shape. See IDEA-GOSPEL-RESOURCES-INTEGRATION-STRATEGY.', + }, +] +const activeTab = ref('charts') + const dash = inject('dashboardData', null) const bus = inject('selectionBus', null) const cfg = inject('dashboardConfig', {}) @@ -105,7 +135,26 @@ useShadowStyles(` .rd-charts::-webkit-scrollbar-track{ background:transparent; } .rd-charts::-webkit-scrollbar-thumb{ background:var(--dx-scroll-thumb, #c4c8c0); border-radius:8px; } .rd-charts::-webkit-scrollbar-thumb:hover{ background:#9aa197; } + /* ★ THE TAB STRIP REPLACES .rd-h, and inherits its exact typography on purpose: weight 700, the + --fs-md token, uppercase, .5px tracking. The rail's visual weight is unchanged, so this reads + as the same header having gained a second option rather than as new chrome appearing. .rd-h is + kept below only because a future rail section may want a plain heading again; it is currently + unused in this file and in every other file under research-dashboard/ (checked). */ .rd-charts .rd-h{ font-weight:700; font-size:var(--fs-md,12px); text-transform:uppercase; letter-spacing:.5px; color:var(--rd-muted, #6d766e); } + .rd-charts .rd-tabs{ display:flex; gap:2px; align-items:stretch; border-bottom:1px solid var(--rd-border, #d1d4cd); margin-bottom:6px; } + .rd-charts .rd-tab{ appearance:none; background:none; border:none; cursor:pointer; + padding:4px 8px 5px; font-family:inherit; font-weight:700; font-size:var(--fs-md,12px); + text-transform:uppercase; letter-spacing:.5px; color:var(--rd-muted, #6d766e); + border-bottom:2px solid transparent; margin-bottom:-1px; white-space:nowrap; } + .rd-charts .rd-tab:hover:not(:disabled){ color:var(--rd-text, #3b463d); } + /* The selected tab is the ACCENT underline plus full-strength text — the same signal the facet + rail uses for an active row, so one visual language covers both rails. */ + .rd-charts .rd-tab.on{ color:var(--rd-text, #3b463d); border-bottom-color:var(--rd-accent, #92b195); } + /* A disabled tab stays LEGIBLE at .45 rather than being hidden: it is a status report, and its + title attribute names the three decisions it waits on. Hiding it would make "not built yet" + and "does not exist" look identical. */ + .rd-charts .rd-tab.off{ opacity:.45; cursor:not-allowed; } + .rd-charts .rd-tab:focus-visible{ outline:2px solid var(--rd-accent, #92b195); outline-offset:-2px; } /* 10px -> 7px 6px: reclaims ~8px of width per card for the plot area itself. */ .rd-chart{ border:1px solid var(--rd-line, #d1d4cd); border-radius:var(--r-lg,10px); background:var(--rd-bg, #f3f3f1); padding:7px 6px; } .rd-chart .rd-ct{ font-weight:700; font-size:var(--fs-sm,11px); color:var(--rd-ink, #3b463d); margin-bottom:6px; } @@ -202,7 +251,31 @@ useShadowStyles(`