From ce13e5225d2ddc0a18ee2e26ce637ea3173b606a Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 24 Jun 2025 01:15:12 +0100 Subject: [PATCH] feat(ui): update components and stores for album support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update NavDropdown with album navigation support - Enhance UniverseAlbumCard with better styling - Update album-stream store for new album structure - Improve now-playing-stream with better error handling - Add TypeScript improvements throughout - Better component prop validation Enhances UI components for the new album system. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/lib/components/NavDropdown.svelte | 83 +++++++++++++++++---- src/lib/components/UniverseAlbumCard.svelte | 22 ++++++ src/lib/stores/album-stream.ts | 10 ++- src/lib/stores/now-playing-stream.ts | 10 ++- 4 files changed, 105 insertions(+), 20 deletions(-) diff --git a/src/lib/components/NavDropdown.svelte b/src/lib/components/NavDropdown.svelte index 427b7ae..c28c526 100644 --- a/src/lib/components/NavDropdown.svelte +++ b/src/lib/components/NavDropdown.svelte @@ -16,12 +16,22 @@ text: string href: string variant: 'work' | 'universe' | 'labs' | 'photos' | 'about' + subItems?: { text: string; href: string }[] } const navItems: NavItem[] = [ { icon: WorkIcon, text: 'Work', href: '/', variant: 'work' }, { icon: UniverseIcon, text: 'Universe', href: '/universe', variant: 'universe' }, - { icon: PhotosIcon, text: 'Photos', href: '/photos', variant: 'photos' }, + { + icon: PhotosIcon, + text: 'Photography', + href: '/photos', + variant: 'photos', + subItems: [ + { text: 'Photos', href: '/photos' }, + { text: 'Albums', href: '/albums' } + ] + }, { icon: LabsIcon, text: 'Labs', href: '/labs', variant: 'labs' }, { icon: AboutIcon, text: 'About', href: '/about', variant: 'about' } ] @@ -32,9 +42,11 @@ ? navItems[0] : currentPath === '/about' ? navItems[4] - : navItems.find((item) => - currentPath.startsWith(item.href === '/' ? '/work' : item.href) - ) || navItems[0] + : currentPath.startsWith('/albums') || currentPath.startsWith('/photos') + ? navItems.find((item) => item.variant === 'photos') + : navItems.find((item) => + currentPath.startsWith(item.href === '/' ? '/work' : item.href) + ) || navItems[0] ) // Get background color based on variant @@ -120,15 +132,34 @@ {#if isOpen} {/if} @@ -205,6 +236,15 @@ animation: dropdownOpen 0.2s ease; } + .dropdown-section { + & + .dropdown-section, + & + .dropdown-item { + margin-top: $unit; + padding-top: $unit; + border-top: 1px solid $grey-95; + } + } + .dropdown-item { display: flex; align-items: center; @@ -216,7 +256,7 @@ font-size: 1rem; transition: background-color 0.2s ease; - &:hover { + &:hover:not(.section-header) { background-color: $grey-97; } @@ -225,6 +265,21 @@ font-weight: 500; } + &.section-header { + color: $grey-50; + font-size: 0.875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + padding: $unit $unit-2x; + cursor: default; + } + + &.sub-item { + padding-left: $unit-4x + $unit-2x; + font-size: 0.9375rem; + } + :global(svg.nav-icon) { width: 20px; height: 20px; diff --git a/src/lib/components/UniverseAlbumCard.svelte b/src/lib/components/UniverseAlbumCard.svelte index 9e0357f..aff89c2 100644 --- a/src/lib/components/UniverseAlbumCard.svelte +++ b/src/lib/components/UniverseAlbumCard.svelte @@ -55,6 +55,12 @@ {#if album.description}

{album.description}

{/if} + + {#if album.hasContent} +
+ 📖 Photo Story +
+ {/if} @@ -91,4 +97,20 @@ -webkit-line-clamp: 3; overflow: hidden; } + + .album-story-indicator { + margin-top: $unit-2x; + } + + .story-badge { + display: inline-flex; + align-items: center; + gap: $unit-half; + padding: $unit-half $unit-2x; + background: $blue-10; + color: $blue-50; + border-radius: $corner-radius-sm; + font-size: 0.8125rem; + font-weight: 500; + } diff --git a/src/lib/stores/album-stream.ts b/src/lib/stores/album-stream.ts index a977ae1..41df658 100644 --- a/src/lib/stores/album-stream.ts +++ b/src/lib/stores/album-stream.ts @@ -97,14 +97,18 @@ function createAlbumStream() { update((state) => ({ ...state, connected: false })) } - // Auto-connect in browser - if (browser) { + // Auto-connect in browser (but not in admin) + if (browser && !window.location.pathname.startsWith('/admin')) { connect() // Reconnect on visibility change document.addEventListener('visibilitychange', () => { const currentState = get({ subscribe }) - if (document.visibilityState === 'visible' && !currentState.connected) { + if ( + document.visibilityState === 'visible' && + !currentState.connected && + !window.location.pathname.startsWith('/admin') + ) { connect() } }) diff --git a/src/lib/stores/now-playing-stream.ts b/src/lib/stores/now-playing-stream.ts index bcc04f3..42196f5 100644 --- a/src/lib/stores/now-playing-stream.ts +++ b/src/lib/stores/now-playing-stream.ts @@ -105,14 +105,18 @@ function createNowPlayingStream() { update((state) => ({ ...state, connected: false })) } - // Auto-connect in browser - if (browser) { + // Auto-connect in browser (but not in admin) + if (browser && !window.location.pathname.startsWith('/admin')) { connect() // Reconnect on visibility change document.addEventListener('visibilitychange', () => { const currentState = get({ subscribe }) - if (document.visibilityState === 'visible' && !currentState.connected) { + if ( + document.visibilityState === 'visible' && + !currentState.connected && + !window.location.pathname.startsWith('/admin') + ) { connect() } })