diff --git a/src/lib/components/AtMentions.svelte b/src/lib/components/AtMentions.svelte index a73389d..cb96068 100644 --- a/src/lib/components/AtMentions.svelte +++ b/src/lib/components/AtMentions.svelte @@ -1,5 +1,6 @@ @@ -32,5 +36,7 @@ data-aturi={aturi || undefined} variant={variant} > + {:else if !failed} + {/if} diff --git a/src/lib/components/LoadingSkeleton.svelte b/src/lib/components/LoadingSkeleton.svelte index ab4de92..33fd291 100644 --- a/src/lib/components/LoadingSkeleton.svelte +++ b/src/lib/components/LoadingSkeleton.svelte @@ -7,17 +7,24 @@ */ interface Props { count?: number; + label?: string; } - let { count = 1 }: Props = $props(); + let { count = 1, label = "Loading content" }: Props = $props(); -{#each Array(count) as _} -
-
-
-{/each} +
+ {#each Array(count) as _} + + {/each} +
diff --git a/src/lib/components/leaflet/LeafletEmbed.svelte b/src/lib/components/leaflet/LeafletEmbed.svelte index 808e874..1f80754 100644 --- a/src/lib/components/leaflet/LeafletEmbed.svelte +++ b/src/lib/components/leaflet/LeafletEmbed.svelte @@ -4,6 +4,8 @@ * Supports explicit height or an aspect-ratio based sizing with * a 16:9 fallback for unmeasured embeds. */ + import LoadingSkeleton from "$lib/components/LoadingSkeleton.svelte"; + let { url, height, aspectRatio }: { url: string; height?: number; @@ -15,9 +17,15 @@ ? `${aspectRatio.width} / ${aspectRatio.height}` : "16 / 9" ); + let loaded = $state(false); -
+
+ {#if !loaded} +
+ +
+ {/if}
diff --git a/src/lib/styles/leaflet-blocks.css b/src/lib/styles/leaflet-blocks.css index f92a366..5e552ea 100644 --- a/src/lib/styles/leaflet-blocks.css +++ b/src/lib/styles/leaflet-blocks.css @@ -252,6 +252,7 @@ /* ── Embeds ─────────────────────────────────────────────────── */ .leaflet-embed { + position: relative; margin: var(--space-md) 0; border-radius: var(--radius-md); overflow: hidden; @@ -259,10 +260,21 @@ } .leaflet-embed iframe { + display: block; width: 100%; border: none; } + .leaflet-embed-loading { + position: absolute; + inset: 0; + z-index: 1; + display: flex; + align-items: center; + padding: var(--space-md); + background: var(--surface-raised); + } + /* ── Website card ───────────────────────────────────────────── */ .leaflet-website-card { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 544be50..dfce9c2 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -20,20 +20,32 @@ let githubUsername = $state('ewanc26'); let publications = $state(null); let links = $state(null); + let homeLoading = $state(true); let pinnedProjects = $derived(githubProjects ? githubProjects.slice(0, 6) : []); onMount(async () => { - // Fetch remaining data in parallel - fetch('/api/home').then(r => r.json()).then(d => { - kibunStatus = d.kibunStatus; - musicStatus = d.musicStatus; - posts = d.posts; - githubProjects = d.githubProjects; - githubUsername = d.githubUsername; - publications = d.publications; - links = d.links; - }).catch(e => console.error("Failed to load home data", e)); + try { + const response = await fetch('/api/home'); + if (!response.ok) throw new Error(`Home API returned ${response.status}`); + + const d = await response.json(); + kibunStatus = d.kibunStatus; + musicStatus = d.musicStatus; + posts = d.posts; + githubProjects = d.githubProjects; + githubUsername = d.githubUsername ?? githubUsername; + publications = d.publications; + links = d.links; + } catch (e) { + console.error("Failed to load home data", e); + posts = []; + githubProjects = []; + publications = []; + links = { cards: [] }; + } finally { + homeLoading = false; + } }); function getBlogUrl(post: any) { @@ -64,7 +76,11 @@ - {#if kibunStatus !== null || musicStatus !== null} + {#if homeLoading} +
+ +
+ {:else if kibunStatus !== null || musicStatus !== null}
{#if kibunStatus}
@@ -92,13 +108,13 @@ {/if} -
+

Blog

Recent writing

{#if posts === null} - + {:else if Array.isArray(posts) && posts.length > 0}
    {#each posts.filter(p => p.publicationRkey === PUBLIC_LEAFLET_BLOG_PUBLICATION).slice(0, 5) as post, i} @@ -123,13 +139,13 @@
-
+

Projects

Pinned on GitHub

{#if githubProjects === null} - + {:else if githubProjects && githubProjects.length > 0}
{#each pinnedProjects as project} @@ -175,13 +191,13 @@
-
+

Publications

Longer-running collections

{#if publications === null} - + {:else if publications && publications.length > 0}
    {#each publications.filter((p: any) => p.rkey !== PUBLIC_LEAFLET_BLOG_PUBLICATION) as pub} @@ -202,13 +218,13 @@
-
+

Elsewhere

Other places to find me

{#if links === null} - + {:else if links && links.cards && links.cards.length > 0}