my website at ewancroft.uk

feat(header): add profile fetching, avatar handling, and layout refinements

ewancroft.uk 3c3a040b 22cc6b75

verified
Changed files
+26 -9
src
lib
components
layout
+26 -9
src/lib/components/layout/Header.svelte
··· 50 50 }); 51 51 </script> 52 52 53 - <header class="sticky top-0 z-50 w-full border-b border-canvas-200 bg-canvas-50/90 backdrop-blur-md dark:border-canvas-800 dark:bg-canvas-950/90"> 54 - <nav class="container mx-auto flex items-center justify-between px-3 py-3 sm:px-4 sm:py-4" aria-label="Main navigation"> 53 + <header 54 + class="sticky top-0 z-50 w-full border-b border-canvas-200 bg-canvas-50/90 backdrop-blur-md dark:border-canvas-800 dark:bg-canvas-950/90" 55 + > 56 + <nav 57 + class="container mx-auto flex items-center justify-between px-3 py-3 sm:px-4 sm:py-4" 58 + aria-label="Main navigation" 59 + > 55 60 <!-- Logo/Avatar with hover title --> 56 - <a href="/" class="group flex min-w-0 shrink items-center gap-2 relative" onclick={closeMobileMenu}> 61 + <a 62 + href="/" 63 + class="group relative flex min-w-0 shrink items-center gap-2" 64 + onclick={closeMobileMenu} 65 + > 57 66 <div class="relative flex items-center"> 58 67 {#if profile?.avatar} 59 68 <img ··· 64 73 /> 65 74 {:else if profile} 66 75 <div 67 - class="flex h-10 w-10 items-center justify-center rounded-full bg-primary-200 text-primary-800 dark:bg-primary-800 dark:text-primary-200 font-bold" 76 + class="flex h-10 w-10 items-center justify-center rounded-full bg-primary-200 font-bold text-primary-800 dark:bg-primary-800 dark:text-primary-200" 68 77 > 69 78 {(profile.displayName || profile.handle).charAt(0).toUpperCase()} 70 79 </div> 71 80 {:else} 72 - <div class="h-10 w-10 rounded-full bg-canvas-300 dark:bg-canvas-700 animate-pulse"></div> 81 + <div class="h-10 w-10 animate-pulse rounded-full bg-canvas-300 dark:bg-canvas-700"></div> 73 82 {/if} 74 83 75 84 <!-- Site title revealed on hover --> 76 85 <span 77 - class="absolute left-full top-1/2 -translate-y-1/2 ml-2 truncate opacity-0 transition-all duration-300 group-hover:opacity-100 sm:ml-3 text-lg font-bold text-ink-900 dark:text-ink-50" 86 + class="absolute top-1/2 left-full ml-2 -translate-y-1/2 truncate text-lg font-bold text-ink-900 opacity-0 transition-all duration-300 group-hover:opacity-100 sm:ml-3 dark:text-ink-50" 78 87 > 79 88 {siteMeta.title} 80 89 </span> ··· 96 105 title={item.label} 97 106 > 98 107 {#if IconComponent} 99 - <IconComponent class="h-5 w-5 transition-transform group-hover:scale-110" aria-hidden="true" /> 108 + <IconComponent 109 + class="h-5 w-5 transition-transform group-hover:scale-110" 110 + aria-hidden="true" 111 + /> 100 112 {:else} 101 113 <div class="flex h-5 w-5 items-center justify-center" aria-hidden="true"> 102 114 <div class="h-3 w-3 animate-pulse rounded-full bg-primary-500"></div> ··· 134 146 135 147 <!-- Mobile Menu Dropdown --> 136 148 {#if mobileMenuOpen} 137 - <div class="border-t border-canvas-200 bg-canvas-50 md:hidden dark:border-canvas-800 dark:bg-canvas-950" role="menu"> 149 + <div 150 + class="border-t border-canvas-200 bg-canvas-50 md:hidden dark:border-canvas-800 dark:bg-canvas-950" 151 + role="menu" 152 + > 138 153 <ul class="container mx-auto flex flex-col px-3 py-2"> 139 154 {#each navItems as item} 140 155 {@const IconComponent = iconComponents[item.href]} ··· 151 166 > 152 167 {#if IconComponent} 153 168 <IconComponent 154 - class="h-5 w-5 {isActive(item.href) ? 'text-primary-600 dark:text-primary-400' : 'text-ink-600 dark:text-ink-400'}" 169 + class="h-5 w-5 {isActive(item.href) 170 + ? 'text-primary-600 dark:text-primary-400' 171 + : 'text-ink-600 dark:text-ink-400'}" 155 172 aria-hidden="true" 156 173 /> 157 174 {:else}