beter crossfade

This commit is contained in:
Vincent van der Wal
2026-08-06 19:24:22 +02:00
parent f4a02a208c
commit 1c5ea2b52e
6 changed files with 276 additions and 199 deletions
@@ -9,6 +9,7 @@
import { storedLocation, storedModel, storedUnits } from '$lib/stores/settings';
import { formatZoned } from '$lib/utils/date';
import { skeletonOut } from '$lib/utils/skeleton-fade';
import { listUnlessDefault, readList, syncSearchParams } from '$lib/utils/url-state';
import { ChartContainer, ChartToolbar } from '$lib/components/charts';
@@ -379,44 +380,49 @@
<!-- chart count derives from the selected variables (not the fetched data),
so the reserved height is right even before the response arrives -->
{#if fetchedData}
<!-- full-bleed graphs until lg / contained card on lg+; titles stay within
the page margins (padded), the graphs bleed to the edges -->
<div class="-mx-3 border-y border-border/70 bg-card shadow-sm lg:mx-0 lg:rounded-2xl lg:border">
{#each chartDefs as def, i (i)}
<div class="px-0 pt-1.5 pb-1 lg:px-4 lg:pb-3 {i > 0 ? 'border-t border-border/50' : ''}">
<div class="mb-1 px-3 lg:px-0">
<h4 class="text-sm font-bold tracking-tight">{def.title}</h4>
{#if def.subtitle}
<p class="text-xs text-muted-foreground">{def.subtitle}</p>
{/if}
<!-- `relative` lets the placeholder dissolve over the finished charts (skeletonOut) -->
<div class="relative">
{#if fetchedData}
<!-- full-bleed graphs until lg / contained card on lg+; titles stay within
the page margins (padded), the graphs bleed to the edges -->
<div class="-mx-3 border-y border-border/70 bg-card shadow-sm lg:mx-0 lg:rounded-2xl lg:border">
{#each chartDefs as def, i (i)}
<div class="px-0 pt-1.5 pb-1 lg:px-4 lg:pb-3 {i > 0 ? 'border-t border-border/50' : ''}">
<div class="mb-1 px-3 lg:px-0">
<h4 class="text-sm font-bold tracking-tight">{def.title}</h4>
{#if def.subtitle}
<p class="text-xs text-muted-foreground">{def.subtitle}</p>
{/if}
</div>
<ChartContainer {loading} chartCount={1} chartHeight={300} minWidth={520} bleed={false}>
<CanvasChart
bind:this={chartComponents[i]}
timestamps={timestampsSec}
timezone={fetchedData.timezone}
series={def.series}
bands={fetchedData.daylightBands}
unit={def.unit}
showCredit={def.showCredit}
{showLegend}
height={300}
group={CHART_GROUP}
/>
</ChartContainer>
</div>
<ChartContainer {loading} chartCount={1} chartHeight={300} minWidth={520} bleed={false}>
<CanvasChart
bind:this={chartComponents[i]}
timestamps={timestampsSec}
timezone={fetchedData.timezone}
series={def.series}
bands={fetchedData.daylightBands}
unit={def.unit}
showCredit={def.showCredit}
{showLegend}
height={300}
group={CHART_GROUP}
/>
</ChartContainer>
</div>
{/each}
</div>
{:else}
<!-- reserve the chart area height before data arrives (no layout shift) -->
<ChartContainer
loading
chartCount={params.hourly?.filter((v) => v !== 'weather_code').length || 1}
chartHeight={340}
bleed={false}
/>
{/if}
{/each}
</div>
{:else}
<!-- reserve the chart area height before data arrives (no layout shift) -->
<div in:fade={{ duration: 200 }} out:skeletonOut>
<ChartContainer
loading
chartCount={params.hourly?.filter((v) => v !== 'weather_code').length || 1}
chartHeight={340}
bleed={false}
/>
</div>
{/if}
</div>
{#if fetchedData && !loading}
<ModelPictogramTimeline