audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

widen track title container, replace inline description with disclosure icon (#1205)

- increase .track-info-wrapper max-width from 600px to min(900px, 90%)
so long titles stay on one line on desktop
- replace collapsible description block with a circled (i) toggle in the
stats row that slides open a metadata panel on click
- only renders when track.description exists

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

authored by

nate nowack
Claude Opus 4.6
and committed by
GitHub
f7aa0310 a1ec41b7

+51 -56
+51 -56
frontend/src/routes/track/[id]/+page.svelte
··· 1 1 <script lang="ts"> 2 - import { fade } from 'svelte/transition'; 2 + import { fade, slide } from 'svelte/transition'; 3 3 import { onMount } from 'svelte'; 4 4 import { browser } from '$app/environment'; 5 5 import { page } from '$app/stores'; ··· 67 67 } 68 68 }); 69 69 70 - // collapsible description 71 - const DESC_COLLAPSED_HEIGHT = 128; // ~5 lines at 1.6 line-height 72 - let descriptionExpanded = $state(false); 73 - let descriptionOverflows = $state(false); 74 - let descriptionEl: HTMLParagraphElement | undefined = $state(); 75 - 76 - $effect(() => { 77 - if (descriptionEl) { 78 - descriptionOverflows = descriptionEl.scrollHeight > DESC_COLLAPSED_HEIGHT; 79 - } 80 - }); 70 + // metadata disclosure panel 71 + let metadataOpen = $state(false); 81 72 82 73 // likers tooltip state 83 74 let showLikersTooltip = $state(false); ··· 576 567 </div> 577 568 {/if} 578 569 579 - {#if track.description} 580 - <div class="track-description-wrapper" class:collapsed={!descriptionExpanded && descriptionOverflows}> 581 - <p class="track-description" bind:this={descriptionEl} style:max-height={!descriptionExpanded && descriptionOverflows ? `${DESC_COLLAPSED_HEIGHT}px` : 'none'}><RichText text={track.description} /></p> 582 - {#if descriptionOverflows} 583 - <button class="description-toggle" onclick={() => descriptionExpanded = !descriptionExpanded}> 584 - {descriptionExpanded ? 'show less ▴' : 'show more ▾'} 585 - </button> 586 - {/if} 587 - </div> 588 - {/if} 589 - 590 570 <div class="track-stats"> 591 571 <span class="plays">{track.play_count} {track.play_count === 1 ? 'play' : 'plays'}</span> 592 572 <LosslessBadge originalFileType={track.original_file_type} fileType={track.file_type} withSeparator separatorClass="separator" /> ··· 616 596 {/if} 617 597 </span> 618 598 {/if} 599 + {#if track.description} 600 + <span class="separator">•</span> 601 + <button 602 + class="metadata-toggle" 603 + class:open={metadataOpen} 604 + onclick={() => metadataOpen = !metadataOpen} 605 + aria-label={metadataOpen ? 'hide details' : 'show details'} 606 + aria-expanded={metadataOpen} 607 + >i</button> 608 + {/if} 619 609 </div> 610 + 611 + {#if track.description && metadataOpen} 612 + <div class="metadata-panel" transition:slide={{ duration: 200 }}> 613 + <p class="metadata-description"><RichText text={track.description} /></p> 614 + </div> 615 + {/if} 620 616 621 617 <div class="side-buttons"> 622 618 {#if auth.isAuthenticated} ··· 847 843 848 844 .track-info-wrapper { 849 845 width: 100%; 850 - max-width: 600px; 846 + max-width: min(900px, 90%); 851 847 display: flex; 852 848 align-items: flex-start; 853 849 justify-content: center; ··· 1008 1004 outline: none; 1009 1005 } 1010 1006 1011 - .track-description-wrapper { 1012 - position: relative; 1013 - margin: 0.75rem 0 0; 1014 - text-align: center; 1007 + .metadata-toggle { 1008 + display: inline-flex; 1009 + align-items: center; 1010 + justify-content: center; 1011 + width: 1.1rem; 1012 + height: 1.1rem; 1013 + border-radius: 50%; 1014 + border: 1px solid var(--text-tertiary); 1015 + color: var(--text-tertiary); 1016 + font-size: 0.65rem; 1017 + font-weight: 600; 1018 + cursor: pointer; 1019 + background: none; 1020 + font-family: inherit; 1021 + line-height: 1; 1022 + transition: color 0.15s, border-color 0.15s; 1023 + padding: 0; 1024 + } 1025 + 1026 + .metadata-toggle:hover, 1027 + .metadata-toggle.open { 1028 + color: var(--accent); 1029 + border-color: var(--accent); 1015 1030 } 1016 1031 1017 - .track-description-wrapper.collapsed .track-description { 1018 - overflow: hidden; 1019 - -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 3rem), transparent); 1020 - mask-image: linear-gradient(to bottom, black calc(100% - 3rem), transparent); 1032 + .metadata-panel { 1033 + margin-top: 0.75rem; 1034 + padding: 0.75rem 0; 1035 + border-top: 1px solid var(--border-subtle); 1036 + text-align: left; 1021 1037 } 1022 1038 1023 - .track-description { 1039 + .metadata-description { 1024 1040 color: var(--text-secondary); 1025 1041 font-size: var(--text-base); 1026 1042 line-height: 1.6; 1027 1043 margin: 0; 1028 1044 white-space: pre-wrap; 1029 - overflow: hidden; 1030 - position: relative; 1031 - } 1032 - 1033 - .description-toggle { 1034 - display: inline-block; 1035 - margin: 0.75rem auto 0; 1036 - padding: 0.25rem 0.75rem; 1037 - background: color-mix(in srgb, var(--text-secondary) 8%, transparent); 1038 - border: 1px solid var(--border-subtle); 1039 - color: var(--text-secondary); 1040 - font-size: var(--text-xs); 1041 - font-family: inherit; 1042 - border-radius: var(--radius-full); 1043 - cursor: pointer; 1044 - transition: all 0.15s ease; 1045 - white-space: nowrap; 1046 - } 1047 - 1048 - .description-toggle:hover { 1049 - color: var(--accent); 1050 - border-color: var(--accent); 1051 - background: color-mix(in srgb, var(--accent) 10%, transparent); 1045 + word-wrap: break-word; 1046 + overflow-wrap: break-word; 1052 1047 } 1053 1048 1054 1049 .track-tags {