layout shifts
This commit is contained in:
@@ -1,9 +1,69 @@
|
||||
<script lang="ts">
|
||||
import { setContext } from 'svelte';
|
||||
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import { storedLocation } from '$lib/stores/settings';
|
||||
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
|
||||
// The location heading lives in the layout, not in each page: a layout
|
||||
// survives navigation, so switching between forecasts no longer tears the
|
||||
// heading down and rebuilds it once the next page's data has loaded.
|
||||
// Page-specific controls (model pickers, range buttons) render into the same
|
||||
// row through this context.
|
||||
let actions = $state<Snippet | null>(null);
|
||||
setContext('weather-hero', {
|
||||
setActions: (snippet: Snippet | null) => {
|
||||
actions = snippet;
|
||||
}
|
||||
});
|
||||
|
||||
// Page data wins; the persisted store covers the moment before the first
|
||||
// load resolves (and any weather page that doesn't carry a location).
|
||||
let location = $derived($page.data.location ?? $storedLocation);
|
||||
|
||||
const SUBTITLES: [string, string][] = [
|
||||
['/weather/week', '7-day forecast'],
|
||||
['/weather/compare', 'Model comparison'],
|
||||
['/weather/14-day', '14-day ensemble forecast'],
|
||||
['/weather/seasonal', 'Seasonal outlook'],
|
||||
['/weather/historical', 'Historical weather']
|
||||
];
|
||||
let subtitle = $derived(
|
||||
SUBTITLES.find(([prefix]) => $page.url.pathname.startsWith(prefix))?.[1] ?? null
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if subtitle && location}
|
||||
<div class="relative mb-3 flex flex-wrap items-center justify-between gap-x-6 gap-y-3 md:mb-5">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<img
|
||||
class="h-10 w-10 shrink-0 rounded-full shadow-sm ring-2 ring-border"
|
||||
src="/images/country-flags/{(location.country_code || 'united_nations').toLowerCase()}.svg"
|
||||
alt={location.country ?? ''}
|
||||
/>
|
||||
<div class="min-w-0">
|
||||
<h1 class="truncate text-2xl leading-tight font-bold tracking-tight md:text-3xl">
|
||||
{location.name}
|
||||
</h1>
|
||||
<p class="truncate text-sm text-muted-foreground">
|
||||
<span class="lg:hidden"
|
||||
>{#if location.admin1}{location.admin1},
|
||||
{/if}{location.country ?? ''}<span class="mx-1 opacity-50">·</span></span
|
||||
>{subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if actions}{@render actions()}{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{@render children?.()}
|
||||
|
||||
Reference in New Issue
Block a user