refactor(layout): replace two-pane split with single-pane navigation

Library and PlayerPanel now display one at a time on all screen sizes.
Selecting a song navigates to the player; the back button returns to
the library. Removes isMobile breakpoint logic and fixed 340px panel width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mistral Vibe
2026-04-10 08:14:56 +02:00
parent d4aad3b8bc
commit b9a83c39cd
2 changed files with 13 additions and 70 deletions

View File

@@ -277,13 +277,10 @@ export function LibraryPanel({ bandId, selectedSongId, onSelectSong }: LibraryPa
return (
<div style={{
width: 340,
minWidth: 280,
flexShrink: 0,
flex: 1,
display: "flex",
flexDirection: "column",
background: "#10131f",
borderRight: `1px solid ${border}`,
height: "100%",
overflow: "hidden",
}}>

View File

@@ -1,28 +1,9 @@
import { useState, useEffect } from "react";
import { useParams, useSearchParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { getBand } from "../api/bands";
import { LibraryPanel } from "../components/LibraryPanel";
import { PlayerPanel } from "../components/PlayerPanel";
// ── Empty player state ────────────────────────────────────────────────────────
function EmptyPlayer() {
return (
<div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", background: "#0c0e1a", gap: 12, padding: 40 }}>
<div style={{ width: 64, height: 64, borderRadius: 20, background: "rgba(139,92,246,0.08)", border: "1px solid rgba(139,92,246,0.15)", display: "flex", alignItems: "center", justifyContent: "center" }}>
<svg width="28" height="28" viewBox="0 0 28 28" fill="none">
<path d="M7 14c0-4.5 3.5-7 7-7s7 2.5 7 7v5L23 22H5l2-3v-5z" stroke="rgba(139,92,246,0.5)" strokeWidth="1.5" strokeLinejoin="round" />
<path d="M10 22a4 4 0 0 0 8 0" stroke="rgba(139,92,246,0.5)" strokeWidth="1.5" />
</svg>
</div>
<p style={{ fontSize: 13, color: "rgba(232,233,240,0.28)", margin: 0, textAlign: "center" }}>
Select a track from the library to start listening
</p>
</div>
);
}
// ── BandPage ──────────────────────────────────────────────────────────────────
export function BandPage() {
@@ -31,15 +12,6 @@ export function BandPage() {
// selectedSongId is kept in URL as ?song=<id> so deep-links and browser back work
const selectedSongId = searchParams.get("song");
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const check = () => setIsMobile(window.innerWidth < 900);
check();
window.addEventListener("resize", check);
return () => window.removeEventListener("resize", check);
}, []);
const { data: band, isLoading } = useQuery({
queryKey: ["band", bandId],
queryFn: () => getBand(bandId!),
@@ -57,9 +29,6 @@ export function BandPage() {
if (isLoading) return <div style={{ color: "rgba(232,233,240,0.35)", padding: 32 }}>Loading</div>;
if (!band || !bandId) return <div style={{ color: "#f87171", padding: 32 }}>Band not found</div>;
// ── Mobile: show library OR player, not both ──────────────────────────────
if (isMobile) {
if (selectedSongId) {
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
@@ -72,6 +41,7 @@ export function BandPage() {
</div>
);
}
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<LibraryPanel
@@ -81,28 +51,4 @@ export function BandPage() {
/>
</div>
);
}
// ── Desktop: three-panel (Sidebar is handled by AppShell, we add Library + Player) ──
return (
<div style={{ display: "flex", height: "100%", overflow: "hidden" }}>
<LibraryPanel
bandId={bandId}
selectedSongId={selectedSongId}
onSelectSong={selectSong}
/>
{selectedSongId ? (
<PlayerPanel
key={selectedSongId}
songId={selectedSongId}
bandId={bandId}
onBack={clearSong}
/>
) : (
<EmptyPlayer />
)}
</div>
);
}