From dea6422f05663955c6ef41588d91d0c551c5b435 Mon Sep 17 00:00:00 2001 From: dcccrypto Date: Thu, 16 Jul 2026 08:38:39 +0100 Subject: [PATCH] fix(ui): music player starts collapsed with a labeled radio pill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expanded by default, the floating transport strip sat over interactive content (the OTHER MARKETS table header on /trade, the table edge on /markets) and nothing anywhere said what it was — an unlabeled play/volume strip reads as broken UI. It now starts as one small music-note pill labeled "Lo-fi radio" (title + aria), expands on click, and remembers the expanded choice in localStorage (restored in an effect to avoid an SSR hydration mismatch). Audio keeps playing while collapsed. Co-Authored-By: Claude Fable 5 --- app/components/ui/MusicPlayer.tsx | 46 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/app/components/ui/MusicPlayer.tsx b/app/components/ui/MusicPlayer.tsx index 34e0e9cd5..71adb3ea9 100644 --- a/app/components/ui/MusicPlayer.tsx +++ b/app/components/ui/MusicPlayer.tsx @@ -66,11 +66,38 @@ function matchesRoute(pathname: string | null | undefined, route: string): boole return pathname === route || pathname.startsWith(route + "/"); } +/** localStorage key remembering that the user expanded the player. */ +const PLAYER_EXPANDED_KEY = "pco-player-expanded"; + export function MusicPlayer() { const [playing, setPlaying] = useState(false); const [volume, setVolume] = useState(0.5); const [progress, setProgress] = useState(0); - const [collapsed, setCollapsed] = useState(false); + // Collapsed by default: expanded, the floating pill sits over interactive + // content (on /trade it covers the OTHER MARKETS table header; on /markets + // the table edge), and an unlabeled transport strip reads as broken UI to + // anyone who doesn't know it's a radio. Start as one small labeled button; + // remember the user's expand across pages (effect below — reading + // localStorage in the initializer would risk an SSR hydration mismatch). + const [collapsed, setCollapsed] = useState(true); + + useEffect(() => { + try { + if (localStorage.getItem(PLAYER_EXPANDED_KEY) === "1") setCollapsed(false); + } catch { + // localStorage unavailable — stay collapsed + } + }, []); + + const expand = useCallback(() => { + setCollapsed(false); + try { localStorage.setItem(PLAYER_EXPANDED_KEY, "1"); } catch {} + }, []); + + const collapse = useCallback(() => { + setCollapsed(true); + try { localStorage.removeItem(PLAYER_EXPANDED_KEY); } catch {} + }, []); const audioRef = useRef(null); const containerRef = useRef(null); @@ -198,18 +225,21 @@ export function MusicPlayer() { {collapsed ? ( ) : ( -
+
{/* Play / Pause */} - @@ -245,7 +275,7 @@ export function MusicPlayer() { {/* Collapse */}