The Driver scrolls further than he should to reach the legend options on a phone, and the note under the legend is why — but not by pushing them down. It was the last child of .legend-content, a natural-height sibling of a flex:1 options panel, so every pixel it took was a pixel the options' own scroller lost. The tree got a shorter viewport and the same rows moved further away. Moving it WITHIN the sheet would have recovered nothing, which is worth stating because it was the obvious reading of the instruction: the sheet's open height is fixed at 30%, so anything inside it costs the options the same wherever it sits. Out here the note costs them nothing and they keep the whole sheet. It is positioned off --legend-sheet-h, which a ResizeObserver already writes for the engine's own bottom controls, so it tracks the sheet as it opens, drags and collapses instead of assuming a height. It stays pointer-events:none with the sheet root: it is text, nothing in it is tappable, and it must never swallow a map drag. The note is kept, not removed — he accepted the text and objected only to it breaking the legend. Its scrim follows `dark` for the same reason the note itself takes that prop: a white halo behind light text is a smear rather than legibility. NEEDS EYES at 390x844: whether it reads over an arbitrary basemap, which is the one thing moving it out of a white panel puts at risk. |
||
|---|---|---|
| .. | ||
| api | ||
| charts | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| data | ||
| elements | ||
| i18n | ||
| layouts | ||
| lists | ||
| maps | ||
| packet | ||
| packets | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| vendor/cldr | ||
| index.js | ||
| ProfileLoader.vue | ||
| README.md | ||
library/ (@map) — the shared map template
The other half of the architecture (see ../plugin-designs/README.md):
every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here.
Fix something here and every map benefits on the next build; break something here and every map
breaks — read components/WARNING.md before touching shared pieces.
| Folder | What lives there |
|---|---|
ProfileLoader.vue |
The root of every bundle: parses profile-config, loads the profile, provides the stores + config |
components/ |
Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README) |
composables/ |
Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming |
stores/ |
Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children |
api/ |
Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring |
colors/ |
Color sets maps opt into via profile-config.colorSet |
i18n/ |
The shared string catalogs (all maps speak the same languages) |
data/ |
Small shared datasets baked at build time (big served data lives in ../data/) |
constants/ |
Shared constants |
scripts/ |
Maintainer pipelines (posters, research) — not part of any bundle |
The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.