Chart counts are a real table column, on the Driver's own prescription
Some checks are pending
build-gate / build (push) Waiting to run

"The number column needs to use some type of TABLE css so the numbers
really are set apart as a column, uniform and justified right, so it does
not move when I scroll left and right."

He is right that table layout is the honest tool: display:table guarantees
every row's count cell shares ONE column edge in every browser ever
shipped. The previous subgrid attempt measured correct here but subgrid is
25 years younger than table layout; the table needs no support caveat.
Rows are table-rows, swatch/label/count are cells; the count cell keeps
sticky right:0 with an opaque background so a scrolling label slides under
a pinned column.

Measured, both legends: display table, cells right-aligned, exactly ONE
unique right edge at rest AND while scrolled. And with the rail widened to
296 in the previous commit, neither legend currently overflows at all --
the wider sidebar bought the words their room, as intended.
This commit is contained in:
doxa-maps-88655c70 2026-09-23 21:35:40 +00:00
parent 564af57c4e
commit d9eca08c44
8 changed files with 74 additions and 76 deletions

View file

@ -198,7 +198,7 @@ useShadowStyles(`
The container is now a two-column GRID (label 1fr, count auto) and every row joins it via
subgrid: ALL counts share the single auto track, so the column is uniform at every scroll
position by construction -- the track IS the column. */
.rd-legend{ display:grid; grid-template-columns:minmax(max-content,1fr) auto; row-gap:2px; font-size:10.5px; color:var(--dx-text, #3b463d); max-height:120px;
.rd-legend{ display:table; border-collapse:separate; border-spacing:0 2px; font-size:10.5px; color:var(--dx-text, #3b463d); max-height:120px;
overflow-y:auto; overflow-x:auto; flex:1 1 auto; min-width:0;
scrollbar-width:thin; scrollbar-color:var(--dx-scroll-thumb, #c4c8c0) transparent; }
.rd-legend::-webkit-scrollbar{ width:6px; height:6px; }
@ -209,15 +209,21 @@ useShadowStyles(`
now two lines tall, and centring would float the swatch and the count in the middle of that
block, detached from the first line of text they label. The count is top-aligned with a 1px
nudge (.rd-li b) so it reads as belonging to the row's first line. */
.rd-li{ display:grid; grid-template-columns:subgrid; grid-column:1 / -1; align-items:start;
cursor:pointer; padding:1px 2px; border-radius:3px; }
.rd-li > i{ grid-column:1; justify-self:start; }
/* the swatch + label share column 1 (the i floats inline before the label) */
.rd-li{ column-gap:6px; }
.rd-li .rd-lt{ grid-column:1; margin-left:14px; }
.rd-li > i{ position:absolute; margin-top:3px; }
.rd-li{ position:relative; }
.rd-li b{ grid-column:2; } /* max-content: the row is as wide as its label, so the scrollport has something to scroll */
/* ★ REAL TABLE CSS, ON THE DRIVER'S OWN PRESCRIPTION (2026-09-23): "the number column needs to
use some type of TABLE css so that the numbers really are set apart as a column, uniform and
justified right, so that it does not move when I scroll left and right." He is right that
table layout is the honest tool here: display:table guarantees every row's second cell shares
ONE column edge in every browser ever shipped -- no subgrid support question, no per-row flex
widths, the column is a column by the layout algorithm itself. (The previous subgrid attempt
measured correct in the built-tree browser but subgrid is younger than table layout by 25
years; the table needs no such caveat.)
The count cell is ALSO sticky right:0 with an opaque background, so when a long label forces
horizontal scroll the numbers stay pinned at the visible edge while the words slide beneath --
the frozen-column behaviour he asked for earlier, now on top of true column geometry. */
.rd-li{ display:table-row; cursor:pointer; }
.rd-li > i{ display:table-cell; width:9px; min-width:9px; padding-top:4px; }
.rd-li .rd-lt{ display:table-cell; padding:1px 6px 1px 5px; }
.rd-li b{ display:table-cell; } /* max-content: the row is as wide as its label, so the scrollport has something to scroll */
.rd-li:hover{ background:var(--dx-surface, #f3f3f1); } .rd-li.on{ background:#fff4ea; font-weight:700; color:var(--rd-ink, #3b463d); }
/* margin-top nudges keep the swatch and the count optically on the label's FIRST line now that
a row can be two lines tall. */
@ -244,11 +250,11 @@ useShadowStyles(`
a little air. sticky right:0 (from the frozen-column fix) is what makes it immovable while the
label scrolls beneath. Both donut legends share .rd-li, so religion and region get this from
the one rule -- which is exactly why it lives here and not per-chart. */
.rd-li b{ position:sticky; right:0; z-index:1; margin-left:auto;
min-width:3.4em; text-align:right;
.rd-li b{ position:sticky; right:0; z-index:1;
min-width:3.4em; text-align:right; white-space:nowrap; vertical-align:top;
background:var(--rd-panel, #fff); box-shadow:-6px 0 6px -4px var(--rd-panel, #fff);
color:var(--rd-muted, #6d766e); font-variant-numeric:tabular-nums; flex:0 0 auto;
padding-left:6px; margin-top:1px; }
color:var(--rd-muted, #6d766e); font-variant-numeric:tabular-nums;
padding:1px 2px 1px 6px; }
/* The label is the ONLY item allowed to shrink. It used to be a bare text node, which in a
nowrap flex row cannot shrink at all: the row grew past .rd-legend (overflow-x:hidden) and
carried the VALUE out of sight — "Ethnoreligion - Chinese Folk Religion" rendered with no

View file

@ -570,28 +570,24 @@
.rd-donut.has-sel .rd-slice{ opacity:.42; }
.rd-slice.on, .rd-donut.has-sel .rd-slice.on{ opacity:1; stroke:var(--rd-ink, #3b463d); stroke-width:2.5;
transform:scale(1.08); filter:drop-shadow(0 1px 2px rgba(31,39,51,.35)); }
.rd-legend{ display:grid; grid-template-columns:minmax(max-content,1fr) auto; row-gap:2px; font-size:10.5px; color:var(--dx-text, #3b463d); max-height:120px;
.rd-legend{ display:table; border-collapse:separate; border-spacing:0 2px; font-size:10.5px; color:var(--dx-text, #3b463d); max-height:120px;
overflow-y:auto; overflow-x:auto; flex:1 1 auto; min-width:0;
scrollbar-width:thin; scrollbar-color:var(--dx-scroll-thumb, #c4c8c0) transparent; }
.rd-legend::-webkit-scrollbar{ width:6px; height:6px; }
.rd-legend::-webkit-scrollbar-track{ background:transparent; }
.rd-legend::-webkit-scrollbar-thumb{ background:var(--dx-scroll-thumb, #c4c8c0); border-radius:6px; }
.rd-legend::-webkit-scrollbar-thumb:hover{ background:#9aa197; }
.rd-li{ display:grid; grid-template-columns:subgrid; grid-column:1 / -1; align-items:start;
cursor:pointer; padding:1px 2px; border-radius:3px; }
.rd-li > i{ grid-column:1; justify-self:start; }
.rd-li{ column-gap:6px; }
.rd-li .rd-lt{ grid-column:1; margin-left:14px; }
.rd-li > i{ position:absolute; margin-top:3px; }
.rd-li{ position:relative; }
.rd-li b{ grid-column:2; }
.rd-li{ display:table-row; cursor:pointer; }
.rd-li > i{ display:table-cell; width:9px; min-width:9px; padding-top:4px; }
.rd-li .rd-lt{ display:table-cell; padding:1px 6px 1px 5px; }
.rd-li b{ display:table-cell; }
.rd-li:hover{ background:var(--dx-surface, #f3f3f1); } .rd-li.on{ background:#fff4ea; font-weight:700; color:var(--rd-ink, #3b463d); }
.rd-li i{ width:9px; height:9px; border-radius:2px; flex:0 0 auto; margin-top:3px; }
.rd-li b{ position:sticky; right:0; z-index:1; margin-left:auto;
min-width:3.4em; text-align:right;
.rd-li b{ position:sticky; right:0; z-index:1;
min-width:3.4em; text-align:right; white-space:nowrap; vertical-align:top;
background:var(--rd-panel, #fff); box-shadow:-6px 0 6px -4px var(--rd-panel, #fff);
color:var(--rd-muted, #6d766e); font-variant-numeric:tabular-nums; flex:0 0 auto;
padding-left:6px; margin-top:1px; }
color:var(--rd-muted, #6d766e); font-variant-numeric:tabular-nums;
padding:1px 2px 1px 6px; }
.rd-lt{ flex:1 1 auto; min-width:0; white-space:nowrap; line-height:1.28; overflow:visible; }
.rd-bars{ display:flex; flex-direction:column; gap:3px; }
.rd-bar{ display:flex; align-items:center; gap:6px; cursor:pointer; font-size:10.5px; padding:1px 2px; border-radius:3px; }

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
<script src="../../dashboard-plus-grid.js" integrity="sha384-zBtRlx3cFqHWsuOochNdwrzQCo6GHsY2MbOY9zGhLS9PqBCAr0cbkdQWRFN3/+Cf" crossorigin="anonymous"></script>
<script src="../../dashboard-plus-grid.js" integrity="sha384-ZJr7t088o8vn8LM4eGvgV1PiFrxP31gt0yXKI8pUexx0ZopPzxt6Rbd83l+B6vMr" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
<script src="../dashboard-plus-grid.js" integrity="sha384-zBtRlx3cFqHWsuOochNdwrzQCo6GHsY2MbOY9zGhLS9PqBCAr0cbkdQWRFN3/+Cf" crossorigin="anonymous"></script>
<script src="../dashboard-plus-grid.js" integrity="sha384-ZJr7t088o8vn8LM4eGvgV1PiFrxP31gt0yXKI8pUexx0ZopPzxt6Rbd83l+B6vMr" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -193,7 +193,7 @@
"bundle": "dashboard-plus-grid",
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"output": "doxa-maps/dashboard-plus-grid/dashboard-plus-grid.js",
"integrity": "sha384-zBtRlx3cFqHWsuOochNdwrzQCo6GHsY2MbOY9zGhLS9PqBCAr0cbkdQWRFN3/+Cf",
"integrity": "sha384-ZJr7t088o8vn8LM4eGvgV1PiFrxP31gt0yXKI8pUexx0ZopPzxt6Rbd83l+B6vMr",
"elements": [
"dashboard-plus-grid"
],
@ -213,7 +213,7 @@
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"embed": {
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-zBtRlx3cFqHWsuOochNdwrzQCo6GHsY2MbOY9zGhLS9PqBCAr0cbkdQWRFN3/+Cf\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-ZJr7t088o8vn8LM4eGvgV1PiFrxP31gt0yXKI8pUexx0ZopPzxt6Rbd83l+B6vMr\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
},
"instances": [
{
@ -878,7 +878,7 @@
"bundle": "research-dashboard",
"scriptUrl": "./research-dashboard/research-dashboard.js",
"output": "doxa-maps/research-dashboard/research-dashboard.js",
"integrity": "sha384-y+QrokwdN8T660MHnspQcvfw8igrKkt+EXDljWQRXGK1XuIPq1wcK8Ed7uYV58nX",
"integrity": "sha384-o3XcsjbqleZU3F/8mtQdGdCLJVgkHReedDapG/VG11tD68poM8jFq9rlg8u6dZKP",
"elements": [
"research-dashboard-map"
],
@ -894,7 +894,7 @@
"scriptUrl": "./research-dashboard/research-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./research-dashboard/research-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-y+QrokwdN8T660MHnspQcvfw8igrKkt+EXDljWQRXGK1XuIPq1wcK8Ed7uYV58nX\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-o3XcsjbqleZU3F/8mtQdGdCLJVgkHReedDapG/VG11tD68poM8jFq9rlg8u6dZKP\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
},
"bundle": "research-dashboard"
}

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <research-dashboard-map> custom element. -->
<script src="../research-dashboard.js" integrity="sha384-y+QrokwdN8T660MHnspQcvfw8igrKkt+EXDljWQRXGK1XuIPq1wcK8Ed7uYV58nX" crossorigin="anonymous"></script>
<script src="../research-dashboard.js" integrity="sha384-o3XcsjbqleZU3F/8mtQdGdCLJVgkHReedDapG/VG11tD68poM8jFq9rlg8u6dZKP" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: