refactor: add SubNav layout and per-subsite nav placeholders; switch Base to use SubNav

This commit is contained in:
2025-11-28 09:07:55 -05:00
parent de50889b2c
commit d8d6c5ec21
26 changed files with 1227 additions and 122 deletions

View File

@@ -1051,25 +1051,23 @@ export default function MediaRequestForm() {
{type === "artist" && albums.length > 0 && (
<>
<div className="flex justify-between items-center mb-2">
<div className="text-sm text-neutral-600 dark:text-neutral-400">
<div className="flex flex-col gap-2 mb-2 sm:flex-row sm:items-center sm:justify-between">
<div className="text-sm text-neutral-600 dark:text-neutral-400 text-center sm:text-left">
<strong className="mr-2">Albums:</strong> {totalAlbums}
<span className="mx-3">|</span>
<span className="mx-3 sm:inline">|</span>
<strong className="mr-2">Tracks:</strong> {totalTracks}
</div>
<div>
<a
href="#"
role="button"
onClick={(e) => {
e.preventDefault(); // prevent page jump
handleToggleAllAlbums();
}}
className="text-sm text-blue-600 hover:underline cursor-pointer"
>
Check / Uncheck All Albums
</a>
</div>
<a
href="#"
role="button"
onClick={(e) => {
e.preventDefault();
handleToggleAllAlbums();
}}
className="text-sm text-blue-600 hover:underline cursor-pointer text-center sm:text-right"
>
Check / Uncheck All Albums
</a>
</div>
<Accordion
multiple
@@ -1148,7 +1146,7 @@ export default function MediaRequestForm() {
{loadingAlbumId === id && <Spinner />}
</span>
<small className="ml-2 text-neutral-500 dark:text-neutral-400">({release_date})</small>
<span className="ml-auto text-xs text-neutral-500">
<span className="ml-0 w-full text-xs text-neutral-500 sm:ml-auto sm:w-auto">
{typeof tracksByAlbum[id] === 'undefined' ? (
loadingAlbumId === id ? 'Loading...' : '...'
) : (
@@ -1171,32 +1169,34 @@ export default function MediaRequestForm() {
return (
<li key={track.id} className="py-2">
<div className="flex items-center gap-3">
<input
type="checkbox"
checked={selected?.includes(String(track.id))}
onChange={() => toggleTrack(id, track.id)}
className="trip-checkbox cursor-pointer"
aria-label={`Select track ${track.title} `}
/>
<button
type="button"
onClick={() => handleTrackPlayPause(track, id, albumIndex)}
className={`flex items-center justify-center w-8 h-8 rounded-full border text-sm transition-colors disabled:opacity-60 disabled:cursor-not-allowed ${isCurrentTrack && isAudioPlaying
? "border-green-600 text-green-600"
: "border-neutral-400 text-neutral-600 hover:text-blue-600 hover:border-blue-600"}`}
aria-label={`${isCurrentTrack && isAudioPlaying ? "Pause" : "Play"} ${track.title}`}
aria-pressed={isCurrentTrack && isAudioPlaying}
disabled={audioLoadingTrackId === track.id}
>
{audioLoadingTrackId === track.id ? (
<InlineSpinner sizeClass="h-4 w-4" />
) : isCurrentTrack && isAudioPlaying ? (
<PauseIcon />
) : (
<PlayIcon />
)}
</button>
<div className="flex flex-wrap items-center gap-3">
<div className="flex items-center gap-3">
<input
type="checkbox"
checked={selected?.includes(String(track.id))}
onChange={() => toggleTrack(id, track.id)}
className="trip-checkbox cursor-pointer"
aria-label={`Select track ${track.title} `}
/>
<button
type="button"
onClick={() => handleTrackPlayPause(track, id, albumIndex)}
className={`flex items-center justify-center w-8 h-8 rounded-full border text-sm transition-colors disabled:opacity-60 disabled:cursor-not-allowed ${isCurrentTrack && isAudioPlaying
? "border-green-600 text-green-600"
: "border-neutral-400 text-neutral-600 hover:text-blue-600 hover:border-blue-600"}`}
aria-label={`${isCurrentTrack && isAudioPlaying ? "Pause" : "Play"} ${track.title}`}
aria-pressed={isCurrentTrack && isAudioPlaying}
disabled={audioLoadingTrackId === track.id}
>
{audioLoadingTrackId === track.id ? (
<InlineSpinner sizeClass="h-4 w-4" />
) : isCurrentTrack && isAudioPlaying ? (
<PauseIcon />
) : (
<PlayIcon />
)}
</button>
</div>
<div className="flex-1 min-w-0 text-left">
<span className="block truncate" title={track.title}>
{truncate(track.title, 80)}
@@ -1207,7 +1207,7 @@ export default function MediaRequestForm() {
</span>
)}
</div>
<div className="flex items-center gap-3 ml-auto text-xs text-neutral-500">
<div className="flex items-center gap-3 text-xs text-neutral-500 w-full justify-between sm:w-auto sm:justify-end">
<button
type="button"
onClick={() => handleTrackDownload(track)}
@@ -1223,7 +1223,7 @@ export default function MediaRequestForm() {
</div>
</div>
{showProgress && (
<div className="mt-2 pr-6 pl-16">
<div className="mt-2 pr-2 pl-4 sm:pr-6 sm:pl-16">
<input
type="range"
min="0"