Skip to content

Commit 1707c59

Browse files
committed
fix(geo): two-panel layout with inline flex, step click handlers
1 parent fbf6600 commit 1707c59

10 files changed

Lines changed: 433 additions & 16 deletions

File tree

.ground_truth.sha256

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
af5dba38c4e66d61cff1ead52ef0349759f23eb77ab03553a8aad85492d0c3f1 GROUND_TRUTH_BRAINSTORM.md
2+
ca6d9eee1b2f20bcea50d46f905a0b76f1b3dde1b684dfbe5ef36726d9a525ef GROUND_TRUTH_DOCS.md
3+
ce23c9872560589d278ca2e1b993a83d2f2c6cf108bf6c256f2a1775b0c52f4b GROUND_TRUTH_HEALTH.md

GROUND_TRUTH_BRAINSTORM.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Ground Truth: Approach
2+
3+
## Map approach: D3 choropleth with TopoJSON (CHOSEN)
4+
- CDN: world-atlas@2/countries-110m.json + topojson-client@3
5+
- d3.geoNaturalEarth1() projection
6+
- Integrated two-panel layout: map left, radar right
7+
- Hover on country → radar shows that region
8+
9+
## Alternative rejected: Leaflet/Mapbox
10+
Over-engineered for this use case. D3 native geo is sufficient.
11+
12+
## Radar refactor approach
13+
Expose window.drawGeoRadarChart(containerId, geoData, options) from geo-radar.js.
14+
geo-map.js calls it to update the side panel. Keep backward compat with scrollama onStep.
15+
16+
## Bubble fix
17+
Simple constant change — BUBBLE_RADIUS_RANGE and TOP_N. No architectural change.

GROUND_TRUTH_DOCS.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Ground Truth: Interfaces
2+
3+
## geo_data.json schema
4+
```json
5+
{
6+
"regions": [
7+
{"name": "Europe", "countries": [...], "count": 15874,
8+
"families": {"floral": N, "woody": N, ...},
9+
"topNotes": [{"note": "musk", "count": N}]}
10+
],
11+
"families": ["floral","woody","citrus","spicy","fresh","sweet","musky","fruity"]
12+
}
13+
```
14+
15+
## geo-radar.js current exports
16+
- window.initGeoRadar(containerId, dataPath) → {onStep}
17+
- REGION_COLORS = {Europe:'#7b9ec9', 'North America':'#c97b7b', Asia:'#7bc9a3', 'Middle East':'#c9b67b', 'South America':'#9b7bc9'}
18+
- normalizeRegion(region) → proportions array
19+
20+
## TopoJSON world-atlas structure
21+
- topojson.feature(world, world.objects.countries) → GeoJSON FeatureCollection
22+
- Each feature.properties.name = country name
23+
- feature.id = ISO numeric code
24+
25+
## CSS variables
26+
--bg-primary:#0a0a0a --accent-gold:#c9a96e --text-primary:#e8e0d4
27+
--text-secondary:#9a9088 --text-muted:#6b6460
28+
--font-heading:'Cormorant Garamond' --font-body:'DM Sans'

GROUND_TRUTH_HEALTH.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Ground Truth: Codebase Health
2+
3+
## Current state (post geo-radar addition)
4+
- 9 viz files in docs/js/visualizations/ (beeswarm, radar, bubbles, timeline, price, chord, sankey, heatmap, geo-radar)
5+
- 8 JSON data files in docs/data/
6+
- geo-radar.js: 376 lines, single overlaid radar, scrollama-driven
7+
- bubbles.js: 365 lines, BUBBLE_RADIUS_RANGE [5,38], TOP_N 40
8+
- main.js: 259 lines, vizConfigs has 9 entries
9+
- index.html: ~280 lines, 8 sections + hero + footer
10+
- style.css: 595 lines
11+
12+
## Key interfaces
13+
- vizConfigs array in main.js: {initFn, containerId, dataPath, scrollyId}
14+
- All vizs: window.initXxx(containerId, dataPath) → {onStep(idx, dir)}
15+
- Shared: NOTE_FAMILIES, getNoteFamily, getNoteColor, FAMILY_COLORS
16+
- Shared: showTooltip, hideTooltip, escapeHtml
17+
18+
## Tech debt
19+
- price.js at 516 lines (over 400 limit)
20+
- No resize handling except heatmap
21+
- geo-radar.js REGION_COLORS defined locally, should be shared if geo-map.js also needs them

TODO.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# TODO — Night Shift geo-map
2+
3+
- [ ] T1: Fix bubbles.js — smaller dots, fewer notes
4+
- [ ] T3: Add "hover to explore" hints in CSS + HTML
5+
- [ ] T4: Enrich geo data — add Indonesia, Malaysia, Lebanon, Egypt
6+
- [ ] T2a: Refactor geo-radar.js — expose reusable drawRadarForRegion
7+
- [ ] T2b: Create geo-map.js — world choropleth + radar integration
8+
- [ ] T2c: Update index.html — two-panel layout, topojson CDN
9+
- [ ] T2d: Update main.js — new vizConfig for geo-map
10+
- [ ] T5: Visual QA — test all sections, screenshots
11+
- [ ] T6: Commit, push, deploy

docs/css/style.css

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -329,32 +329,68 @@ strong {
329329
GEO MAP + RADAR LAYOUT
330330
============================================ */
331331

332+
.geo-section-layout {
333+
max-width: var(--content-width);
334+
margin: 0 auto;
335+
padding: 0 2.5rem;
336+
}
337+
332338
.geo-layout {
333339
display: flex;
334340
gap: 1.5rem;
335341
width: 100%;
336-
height: 100%;
337-
min-height: 400px;
342+
height: 500px;
338343
}
339344

340345
.geo-map-container {
341-
flex: 1.2;
346+
flex: 1.3;
342347
min-width: 0;
343348
position: relative;
349+
background: var(--bg-card);
350+
border: 1px solid var(--border-subtle);
351+
border-radius: 16px;
352+
overflow: hidden;
344353
}
345354

346355
.geo-radar-container {
347-
flex: 0.8;
356+
flex: 0.7;
348357
min-width: 0;
358+
background: var(--bg-card);
359+
border: 1px solid var(--border-subtle);
360+
border-radius: 16px;
349361
display: flex;
350362
align-items: center;
351363
justify-content: center;
352364
}
353365

354-
.geo-map-container svg,
355-
.geo-radar-container svg {
356-
width: 100%;
357-
height: 100%;
366+
.geo-steps {
367+
display: flex;
368+
gap: 1rem;
369+
margin-top: 1.5rem;
370+
}
371+
372+
.geo-steps .step {
373+
flex: 1;
374+
padding: 1.5rem;
375+
margin-bottom: 0;
376+
background: var(--bg-card);
377+
border: 1px solid var(--border-subtle);
378+
border-radius: 12px;
379+
opacity: 0.5;
380+
transition: opacity 0.4s ease, border-color 0.4s ease;
381+
cursor: pointer;
382+
}
383+
384+
.geo-steps .step.is-active {
385+
opacity: 1;
386+
border-color: var(--border-active);
387+
}
388+
389+
.geo-steps .step p {
390+
font-size: 0.9rem;
391+
font-weight: 300;
392+
line-height: 1.7;
393+
color: var(--text-primary);
358394
}
359395

360396
/* ============================================
@@ -578,6 +614,10 @@ strong {
578614
min-height: 300px;
579615
}
580616

617+
.geo-steps {
618+
flex-direction: column;
619+
}
620+
581621
.nav-links {
582622
display: none;
583623
}

docs/index.html

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,12 @@ <h2 class="section-title">The Geography of Scent</h2>
235235
How does composition vary across world regions?
236236
</p>
237237
</div>
238-
<div class="scrolly" id="scrolly-geo-map">
239-
<div class="scrolly-graphic sticky">
240-
<div class="geo-layout">
241-
<div class="geo-map-container" id="viz-geo-map"></div>
242-
<div class="geo-radar-container" id="viz-geo-radar-side"></div>
243-
</div>
238+
<div class="geo-section-layout">
239+
<div class="geo-layout" id="scrolly-geo-map" style="display:flex">
240+
<div class="geo-map-container" id="viz-geo-map"></div>
241+
<div class="geo-radar-container" id="viz-geo-radar-side"></div>
244242
</div>
245-
<div class="scrolly-steps">
243+
<div class="geo-steps">
246244
<div class="step" data-step="1">
247245
<p><strong>Europe</strong> leads with floral dominance — jasmine and rose are the continent's signatures. With over 15,000 perfumes, European houses set the global standard.</p>
248246
</div>

docs/js/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@
215215
{ initFn: 'initChord', containerId: 'viz-chord', dataPath: 'data/chord_data.json', scrollyId: null },
216216
{ initFn: 'initSankey', containerId: 'viz-sankey', dataPath: 'data/sankey_data.json', scrollyId: null },
217217
{ initFn: 'initHeatmap', containerId: 'viz-heatmap', dataPath: 'data/accords_data.json', scrollyId: null },
218-
{ initFn: 'initGeoMap', containerId: 'viz-geo-map', dataPath: 'data/geo_data.json', scrollyId: 'scrolly-geo-map' },
218+
{ initFn: 'initGeoMap', containerId: 'viz-geo-map', dataPath: 'data/geo_data.json', scrollyId: null },
219219
];
220220

221221
function lazyInitViz(config) {

docs/js/visualizations/geo-map.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,19 @@
261261
drawSideRadar(radarContainer, geoData, null);
262262
}
263263

264+
var geoSteps = document.querySelectorAll('.geo-steps .step');
265+
if (geoSteps.length > 0) {
266+
geoSteps[0].classList.add('is-active');
267+
onStep(0);
268+
geoSteps.forEach(function (stepEl, idx) {
269+
stepEl.addEventListener('click', function () {
270+
geoSteps.forEach(function (s) { s.classList.remove('is-active'); });
271+
stepEl.classList.add('is-active');
272+
onStep(idx);
273+
});
274+
});
275+
}
276+
264277
}).catch(function (err) {
265278
console.error('GeoMap: failed to load data —', err);
266279
});

0 commit comments

Comments
 (0)