From dbfa38f6c584f186de75cc31a739881661e142aa Mon Sep 17 00:00:00 2001 From: Vincent van der Wal Date: Mon, 3 Aug 2026 11:39:56 +0200 Subject: [PATCH] read more text --- messages/de.json | 4 +- messages/en.json | 4 +- messages/es.json | 4 +- messages/fr.json | 4 +- messages/it.json | 4 +- .../weather/week/[location]/+page.svelte | 55 ++++++++-- .../weather/week/[location]/DaySummary.svelte | 100 ++++++++++++++++-- 7 files changed, 151 insertions(+), 24 deletions(-) diff --git a/messages/de.json b/messages/de.json index 8ae4807..3c55855 100644 --- a/messages/de.json +++ b/messages/de.json @@ -363,5 +363,7 @@ "wmo_86": "Starke Schneeschauer", "wmo_95": "Gewitter", "wmo_96": "Gewitter mit leichtem Hagel", - "wmo_99": "Gewitter mit starkem Hagel" + "wmo_99": "Gewitter mit starkem Hagel", + "summary_read_more": "Mehr anzeigen", + "summary_read_less": "Weniger anzeigen" } diff --git a/messages/en.json b/messages/en.json index 536c18c..60958e8 100644 --- a/messages/en.json +++ b/messages/en.json @@ -363,5 +363,7 @@ "wmo_86": "Heavy snow showers", "wmo_95": "Thunderstorm", "wmo_96": "Thunderstorm with slight hail", - "wmo_99": "Thunderstorm with heavy hail" + "wmo_99": "Thunderstorm with heavy hail", + "summary_read_more": "Read more", + "summary_read_less": "Show less" } diff --git a/messages/es.json b/messages/es.json index fc4aff5..c6e0efe 100644 --- a/messages/es.json +++ b/messages/es.json @@ -363,5 +363,7 @@ "wmo_86": "Chubascos de nieve intensos", "wmo_95": "Tormenta", "wmo_96": "Tormenta con granizo ligero", - "wmo_99": "Tormenta con granizo fuerte" + "wmo_99": "Tormenta con granizo fuerte", + "summary_read_more": "Leer más", + "summary_read_less": "Mostrar menos" } diff --git a/messages/fr.json b/messages/fr.json index 1b7a88f..e057603 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -363,5 +363,7 @@ "wmo_86": "Averses de neige fortes", "wmo_95": "Orage", "wmo_96": "Orage avec grêle légère", - "wmo_99": "Orage avec forte grêle" + "wmo_99": "Orage avec forte grêle", + "summary_read_more": "Lire la suite", + "summary_read_less": "Afficher moins" } diff --git a/messages/it.json b/messages/it.json index c43c69c..fe570ba 100644 --- a/messages/it.json +++ b/messages/it.json @@ -363,5 +363,7 @@ "wmo_86": "Rovesci di neve forti", "wmo_95": "Temporale", "wmo_96": "Temporale con grandine leggera", - "wmo_99": "Temporale con grandine forte" + "wmo_99": "Temporale con grandine forte", + "summary_read_more": "Leggi tutto", + "summary_read_less": "Mostra meno" } diff --git a/src/routes/weather/week/[location]/+page.svelte b/src/routes/weather/week/[location]/+page.svelte index afb8257..06573f8 100644 --- a/src/routes/weather/week/[location]/+page.svelte +++ b/src/routes/weather/week/[location]/+page.svelte @@ -85,10 +85,21 @@ // arrives (no layout shift) let enabledChartCount = $derived($storedChartLayout.filter((p) => p.variables.length > 0).length); - // The hourly table is a header row plus one row per enabled variable, so the - // placeholder below reserves exactly that and nothing under it jumps when the - // real table arrives. - const TABLE_ROW_PX = 57; + // The hourly table is a header row, the time/daylight row, then one row per + // enabled variable, so the placeholder below reserves exactly that and + // nothing under it jumps when the real table arrives. Rows are shorter below + // lg, where the cells sit tighter - measured, not guessed: 36px against 55px, + // and the time row is 48px at every width. + let compactRows = $state(false); + onMount(() => { + const mq = window.matchMedia('(max-width: 1023px)'); + const apply = () => (compactRows = mq.matches); + apply(); + mq.addEventListener('change', apply); + return () => mq.removeEventListener('change', apply); + }); + let tableRowPx = $derived(compactRows ? 36 : 55); + const TABLE_TIME_ROW_PX = 48; let enabledTableRows = $derived(Object.values($storedVariablePrefs.table).filter(Boolean).length); // Request only the hourly variables the table rows and meteograms actually @@ -490,8 +501,13 @@
+ +
+
+
+
{#each { length: enabledTableRows } as _, i (i)} -
+
@@ -505,10 +521,16 @@
{:else} - +
-
+
{/if} @@ -526,14 +548,27 @@
-
+ +
- + +
{/if} diff --git a/src/routes/weather/week/[location]/DaySummary.svelte b/src/routes/weather/week/[location]/DaySummary.svelte index 538131d..100cac1 100644 --- a/src/routes/weather/week/[location]/DaySummary.svelte +++ b/src/routes/weather/week/[location]/DaySummary.svelte @@ -96,6 +96,35 @@ return `M 0 ${-R} A ${R} ${R} 0 0 ${outerSweep} 0 ${R} A ${rx} ${R} 0 0 ${innerSweep} 0 ${-R} Z`; }); let illumination = $derived(finite(phase) ? Math.round(moonIllumination(phase) * 100) : null); + + // ─── Narrative clamp (phones only) ────────────────────────────────────────── + // The narrative runs anywhere from two to nine lines depending on the day, + // which on a phone means the whole page below it moves as soon as the data + // lands. Below md the text is clamped to five lines and gets a toggle, and + // the block reserves those five lines plus the toggle row whatever the + // length - so the card is the same height before and after the fetch, and the + // skeleton can match it exactly. From md up nothing is clamped. + + let expanded = $state(false); + let textEl = $state(); + let overflows = $state(false); + + $effect(() => { + sentences; // re-measure when the day (and so the text) changes + const el = textEl; + if (!el || expanded) return; // measuring while open would always say "fits" + + const measure = () => { + // only clamped below md, where the toggle is the only way to see the rest + const clamped = window.matchMedia('(max-width: 767px)').matches; + overflows = clamped && el.scrollHeight - el.clientHeight > 1; + }; + measure(); + + const observer = new ResizeObserver(measure); + observer.observe(el); + return () => observer.disconnect(); + });
@@ -115,15 +144,35 @@
- {#if sentences.length > 0} -

- {sentences.join(' ')} -

- {:else} -

- {m.summary_no_data()} -

- {/if} +
+ {#if sentences.length > 0} +

+ {sentences.join(' ')} +

+ {:else} +

+ {m.summary_no_data()} +

+ {/if} + + + +
+ +