fix: playlist menus and link previews (#509)

- fix stopPropagation blocking link clicks in AddToMenu and TrackActionsMenu
- add /playlist/ to hasPageMetadata so layout default OG tags don't override
- replace LikeButton with AddToMenu on track detail page for playlist access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>

authored by zzstoatzz.io Claude and committed by GitHub 12c76e63 e1cba451

Changed files
+30 -5
frontend
+7 -1
frontend/src/lib/components/AddToMenu.svelte
··· 184 184 185 185 {#if menuOpen} 186 186 <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions --> 187 - <div class="menu-dropdown" role="menu" tabindex="-1" onclick={(e) => e.stopPropagation()}> 187 + <div class="menu-dropdown" role="menu" tabindex="-1" onclick={(e) => { 188 + // don't stop propagation for links - let SvelteKit handle navigation 189 + if (e.target instanceof HTMLAnchorElement || (e.target as HTMLElement).closest('a')) { 190 + return; 191 + } 192 + e.stopPropagation(); 193 + }}> 188 194 {#if !showPlaylistPicker} 189 195 <button class="menu-item" onclick={handleLike} disabled={loading}> 190 196 <svg width="18" height="18" viewBox="0 0 24 24" fill={liked ? 'currentColor' : 'none'} stroke="currentColor" stroke-width="2">
+7 -1
frontend/src/lib/components/TrackActionsMenu.svelte
··· 190 190 <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions --> 191 191 <div class="menu-backdrop" role="presentation" onclick={closeMenu}></div> 192 192 <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions --> 193 - <div class="menu-panel" role="menu" tabindex="-1" onclick={(e) => e.stopPropagation()}> 193 + <div class="menu-panel" role="menu" tabindex="-1" onclick={(e) => { 194 + // don't stop propagation for links - let SvelteKit handle navigation 195 + if (e.target instanceof HTMLAnchorElement || (e.target as HTMLElement).closest('a')) { 196 + return; 197 + } 198 + e.stopPropagation(); 199 + }}> 194 200 {#if !showPlaylistPicker} 195 201 {#if isAuthenticated} 196 202 <button class="menu-item" onclick={handleLike} disabled={loading || likeDisabled} class:disabled={likeDisabled}>
+1
frontend/src/routes/+layout.svelte
··· 28 28 let hasPageMetadata = $derived( 29 29 $page.url.pathname === '/' || // homepage 30 30 $page.url.pathname.startsWith('/track/') || // track detail 31 + $page.url.pathname.startsWith('/playlist/') || // playlist detail 31 32 $page.url.pathname === '/liked' || // liked tracks 32 33 $page.url.pathname.match(/^\/u\/[^/]+$/) || // artist detail 33 34 $page.url.pathname.match(/^\/u\/[^/]+\/album\/[^/]+/) // album detail
+15 -3
frontend/src/routes/track/[id]/+page.svelte
··· 5 5 import { APP_NAME, APP_CANONICAL_URL } from '$lib/branding'; 6 6 import { API_URL } from '$lib/config'; 7 7 import Header from '$lib/components/Header.svelte'; 8 - import LikeButton from '$lib/components/LikeButton.svelte'; 8 + import AddToMenu from '$lib/components/AddToMenu.svelte'; 9 9 import ShareButton from '$lib/components/ShareButton.svelte'; 10 10 import TagEffects from '$lib/components/TagEffects.svelte'; 11 11 import SensitiveImage from '$lib/components/SensitiveImage.svelte'; ··· 387 387 <div class="track-info-wrapper"> 388 388 <div class="side-button-left"> 389 389 {#if auth.isAuthenticated} 390 - <LikeButton trackId={track.id} trackTitle={track.title} initialLiked={track.is_liked || false} /> 390 + <AddToMenu 391 + trackId={track.id} 392 + trackTitle={track.title} 393 + trackUri={track.atproto_record_uri} 394 + trackCid={track.atproto_record_cid} 395 + initialLiked={track.is_liked || false} 396 + /> 391 397 {/if} 392 398 </div> 393 399 ··· 439 445 440 446 <div class="mobile-side-buttons"> 441 447 {#if auth.isAuthenticated} 442 - <LikeButton trackId={track.id} trackTitle={track.title} initialLiked={track.is_liked || false} /> 448 + <AddToMenu 449 + trackId={track.id} 450 + trackTitle={track.title} 451 + trackUri={track.atproto_record_uri} 452 + trackCid={track.atproto_record_cid} 453 + initialLiked={track.is_liked || false} 454 + /> 443 455 {/if} 444 456 <ShareButton url={shareUrl} title="share track" /> 445 457 </div>