Skip to content

Commit ce51512

Browse files
authored
Fix frontend CI failures and polish story-map rendering (#20)
* fix: restore frontend type-check for busiest rail chart * fix: resolve MiSans font assets during frontend build * fix: improve busiest rail chart fit on smaller screens * style: align story panel width with page layout * feat: improve map loading states and dev asset serving * perf: serve lightweight swiss boundary skeleton
1 parent 6cf3c38 commit ce51512

9 files changed

Lines changed: 232 additions & 60 deletions

File tree

docs/public/data/swiss_boundary_skeleton.svg

Lines changed: 3 additions & 0 deletions
Loading

docs/public/fonts/misans/misans.css

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,70 @@
11
@font-face {
22
font-family: 'MiSans Latin';
3-
src: url('/fonts/misans/woff2/MiSansLatin-Thin.woff2') format('woff2');
3+
src: url('./woff2/MiSansLatin-Thin.woff2') format('woff2');
44
font-weight: 100;
55
font-style: normal;
66
font-display: swap;
77
}
88

99
@font-face {
1010
font-family: 'MiSans Latin';
11-
src: url('/fonts/misans/woff2/MiSansLatin-ExtraLight.woff2') format('woff2');
11+
src: url('./woff2/MiSansLatin-ExtraLight.woff2') format('woff2');
1212
font-weight: 200;
1313
font-style: normal;
1414
font-display: swap;
1515
}
1616

1717
@font-face {
1818
font-family: 'MiSans Latin';
19-
src: url('/fonts/misans/woff2/MiSansLatin-Light.woff2') format('woff2');
19+
src: url('./woff2/MiSansLatin-Light.woff2') format('woff2');
2020
font-weight: 300;
2121
font-style: normal;
2222
font-display: swap;
2323
}
2424

2525
@font-face {
2626
font-family: 'MiSans Latin';
27-
src: url('/fonts/misans/woff2/MiSansLatin-Regular.woff2') format('woff2');
27+
src: url('./woff2/MiSansLatin-Regular.woff2') format('woff2');
2828
font-weight: 400;
2929
font-style: normal;
3030
font-display: swap;
3131
}
3232

3333
@font-face {
3434
font-family: 'MiSans Latin';
35-
src: url('/fonts/misans/woff2/MiSansLatin-Medium.woff2') format('woff2');
35+
src: url('./woff2/MiSansLatin-Medium.woff2') format('woff2');
3636
font-weight: 500;
3737
font-style: normal;
3838
font-display: swap;
3939
}
4040

4141
@font-face {
4242
font-family: 'MiSans Latin';
43-
src: url('/fonts/misans/woff2/MiSansLatin-Demibold.woff2') format('woff2');
43+
src: url('./woff2/MiSansLatin-Demibold.woff2') format('woff2');
4444
font-weight: 600;
4545
font-style: normal;
4646
font-display: swap;
4747
}
4848

4949
@font-face {
5050
font-family: 'MiSans Latin';
51-
src: url('/fonts/misans/woff2/MiSansLatin-Semibold.woff2') format('woff2');
51+
src: url('./woff2/MiSansLatin-Semibold.woff2') format('woff2');
5252
font-weight: 650;
5353
font-style: normal;
5454
font-display: swap;
5555
}
5656

5757
@font-face {
5858
font-family: 'MiSans Latin';
59-
src: url('/fonts/misans/woff2/MiSansLatin-Bold.woff2') format('woff2');
59+
src: url('./woff2/MiSansLatin-Bold.woff2') format('woff2');
6060
font-weight: 700;
6161
font-style: normal;
6262
font-display: swap;
6363
}
6464

6565
@font-face {
6666
font-family: 'MiSans Latin';
67-
src: url('/fonts/misans/woff2/MiSansLatin-Heavy.woff2') format('woff2');
67+
src: url('./woff2/MiSansLatin-Heavy.woff2') format('woff2');
6868
font-weight: 800;
6969
font-style: normal;
7070
font-display: swap;

frontend/src/components/BusiestRailChart.vue

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,15 @@ function draw() {
6161
6262
const rows = [...activePreset.value.stations].reverse()
6363
const w = container.clientWidth || 640
64-
const h = 360
65-
const margin = { top: 8, right: 28, bottom: 36, left: 132 }
64+
const availableHeight = container.clientHeight || 360
65+
const h = Math.max(Math.min(availableHeight, 360), 240)
66+
const compact = h < 320 || w < 640
67+
const margin = {
68+
top: 8,
69+
right: compact ? 20 : 28,
70+
bottom: compact ? 32 : 36,
71+
left: compact ? 112 : 132,
72+
}
6673
6774
const innerW = w - margin.left - margin.right
6875
const innerH = h - margin.top - margin.bottom
@@ -107,18 +114,18 @@ function draw() {
107114
.call(d3.axisBottom(x).ticks(5).tickSizeOuter(0))
108115
.selectAll('text')
109116
.attr('fill', '#7a6568')
110-
.attr('font-size', '11px')
117+
.attr('font-size', compact ? '10px' : '11px')
111118
112119
g.selectAll('.x-axis path, .x-axis line')
113120
.transition(t as any)
114121
.attr('stroke', 'rgba(120,90,92,0.35)')
115122
116123
g.select('.x-axis-label')
117124
.attr('x', innerW)
118-
.attr('y', innerH + 30)
125+
.attr('y', innerH + (compact ? 26 : 30))
119126
.attr('text-anchor', 'end')
120127
.attr('fill', '#8a7070')
121-
.attr('font-size', '11px')
128+
.attr('font-size', compact ? '10px' : '11px')
122129
.text('Unique rail trips')
123130
124131
g.selectAll('rect.bar')
@@ -155,43 +162,46 @@ function draw() {
155162
.attr('dy', '0.35em')
156163
.attr('text-anchor', 'end')
157164
.attr('fill', '#3d3335')
158-
.attr('font-size', '11px')
165+
.attr('font-size', compact ? '10px' : '11px')
159166
.attr('font-weight', '600')
160167
.text((d: any) => d.name)
161168
.attr('opacity', 0)
162169
.call(e => e.transition(t as any).attr('opacity', 1)),
163170
update => update
164171
.call(u => u.transition(t as any)
165172
.attr('y', (d: any) => (y(d.name) || 0) + y.bandwidth() / 2)
173+
.attr('font-size', compact ? '10px' : '11px')
166174
.attr('opacity', 1)
167175
),
168176
exit => exit.call(ex => ex.transition(t as any).attr('opacity', 0).remove())
169177
)
170178
171-
g.selectAll('text.val')
172-
.data(rows, (d: any) => d.name)
179+
g.selectAll<SVGTextElement, Row>('text.val')
180+
.data(rows, (d: Row) => d.name)
173181
.join(
174182
enter => enter.append('text')
175183
.attr('class', 'val')
176-
.attr('x', (d: any) => x(d.trips) + 6)
177-
.attr('y', (d: any) => (y(d.name) || 0) + y.bandwidth() / 2)
184+
.attr('x', (d: Row) => x(d.trips) + 6)
185+
.attr('y', (d: Row) => (y(d.name) || 0) + y.bandwidth() / 2)
178186
.attr('dy', '0.35em')
179187
.attr('fill', '#5b4b4d')
180-
.attr('font-size', '10px')
188+
.attr('font-size', compact ? '9px' : '10px')
181189
.attr('opacity', 0)
182-
.text((d: any) => d.trips)
190+
.text((d: Row) => d.trips)
183191
.call(e => e.transition(t as any).attr('opacity', 1)),
184192
update => update
185193
.call(u => u.transition(t as any)
186-
.attr('x', (d: any) => x(d.trips) + 6)
187-
.attr('y', (d: any) => (y(d.name) || 0) + y.bandwidth() / 2)
194+
.attr('x', (d: Row) => x(d.trips) + 6)
195+
.attr('y', (d: Row) => (y(d.name) || 0) + y.bandwidth() / 2)
196+
.attr('font-size', compact ? '9px' : '10px')
188197
.attr('opacity', 1)
189-
.tween('text', function(this: SVGTextElement, d: any) {
190-
const startStr = this.textContent || '0'
198+
.tween('text', function(d: Row) {
199+
const node = this as SVGTextElement
200+
const startStr = node.textContent || '0'
191201
const startVal = parseInt(startStr.replace(/,/g, ''), 10) || 0
192202
const iter = d3.interpolateRound(startVal, d.trips)
193203
return function(tParam: number) {
194-
this.textContent = iter(tParam).toString()
204+
node.textContent = iter(tParam).toString()
195205
}
196206
})
197207
),
@@ -250,11 +260,6 @@ function onEndInput(e: Event) {
250260
<div class="chart-heading">
251261
<span class="chart-kicker">Load</span>
252262
<h3 class="chart-title">Where the morning concentrates</h3>
253-
<p class="chart-lead">
254-
Drag the morning open or shut. Each bar is a doorway: how many <em>different</em> trains touch that platform
255-
while your window is running. The reds are the crowd favourites; the pale yellows are still busy, just not
256-
centre stage.
257-
</p>
258263
</div>
259264

260265
<div v-if="loadError" class="chart-fallback">
@@ -336,19 +341,19 @@ function onEndInput(e: Event) {
336341
color: #1f1819;
337342
}
338343
339-
.chart-lead {
340-
margin: 10px 0 0;
341-
font-size: 0.88rem;
342-
line-height: 1.55;
343-
color: #6b5c5e;
344-
}
345-
346344
.chart-fallback {
347345
font-size: 0.86rem;
348346
color: #7a4b4f;
349347
line-height: 1.55;
350348
}
351349
350+
.chart-body {
351+
display: flex;
352+
flex-direction: column;
353+
flex: 1;
354+
min-height: 0;
355+
}
356+
352357
.chart-fallback code {
353358
font-family: ui-monospace, monospace;
354359
font-size: 0.8rem;
@@ -427,13 +432,64 @@ function onEndInput(e: Event) {
427432
display: flex;
428433
flex-direction: column;
429434
flex: 1;
430-
min-height: 0;
435+
min-height: 240px;
431436
}
432437
433438
.chart-svg {
434439
display: block;
435440
width: 100%;
441+
height: 100%;
436442
flex: 1;
437-
min-height: 0;
443+
min-height: 240px;
444+
}
445+
446+
@media (max-height: 860px) {
447+
.chart-shell {
448+
gap: 14px;
449+
padding: 18px 20px 22px;
450+
}
451+
452+
.chart-title {
453+
font-size: 1.2rem;
454+
}
455+
456+
.sliders {
457+
gap: 14px 20px;
458+
}
459+
460+
.slider-block {
461+
min-width: 170px;
462+
}
463+
}
464+
465+
@media (max-height: 760px) {
466+
.chart-shell {
467+
gap: 12px;
468+
padding: 16px 18px 18px;
469+
}
470+
471+
.chart-kicker,
472+
.slider-label {
473+
font-size: 0.64rem;
474+
}
475+
476+
.chart-title {
477+
font-size: 1.08rem;
478+
}
479+
480+
.slider-value,
481+
.window-pill,
482+
.window-approx {
483+
font-size: 0.74rem;
484+
}
485+
486+
.window-line {
487+
gap: 8px 10px;
488+
}
489+
490+
.chart-wrap,
491+
.chart-svg {
492+
min-height: 220px;
493+
}
438494
}
439495
</style>

0 commit comments

Comments
 (0)