From 985e4e5e6d0f095721aa33769eab09ec65cca0eb Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Sat, 20 Jun 2026 20:39:49 +0200 Subject: [PATCH 1/3] fix(mini-player): restore provider order after per-profile theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ThemeProvider grew a `useProfile()` call in #264 (per-profile theme + skin storage), but MiniPlayerApp.tsx was left with the legacy nesting where ThemeProvider wraps ProfileProvider. React StrictMode catches the "must be used within ProfileProvider" throw and surfaces it as a white window — mini-player has been blanked since 1.5.0. Mirror the main App.tsx nesting (ProfileProvider outer) so the mini boots into the same provider chain. --- src/MiniPlayerApp.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/MiniPlayerApp.tsx b/src/MiniPlayerApp.tsx index 9d4dd9fd..639fb592 100644 --- a/src/MiniPlayerApp.tsx +++ b/src/MiniPlayerApp.tsx @@ -9,6 +9,12 @@ import { MiniPlayer } from "./components/views/MiniPlayer"; * Library / Playlist contexts since the mini-player only displays * the current track + playback controls — no library browsing. * + * ProfileProvider sits OUTSIDE ThemeProvider because the per-profile + * theme work landed in #264 made `ThemeProvider` call `useProfile()` + * to scope theme choices per-profile. Without this nesting the + * mini boots into a white screen via the "must be used within + * ProfileProvider" throw — mirrors the main `App.tsx` nesting. + * * SpotifyProvider stays in because PlayerProvider calls useSpotify() * unconditionally (provider routing happens inside PlayerContext). * Without it the mini boots into a white screen via the "must be @@ -20,14 +26,14 @@ import { MiniPlayer } from "./components/views/MiniPlayer"; */ export function MiniPlayerApp() { return ( - - + + - - + + ); } From a066a17948f756b848a2e1857e06e31b7ad10224 Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Sat, 20 Jun 2026 20:40:00 +0200 Subject: [PATCH 2/3] fix(skins): drop shadowCard from skin picker preview (Pulse leak) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pulse's shadowCard is a neon halo `0 0 24px -4px var(--accent-500)` that leaks visibly past the picker button's overflow-hidden clip in the Settings → Appearance grid. The other skins' shadows are either too subtle (Studio's 1px black, Lounge's soft drop) or absent (Editorial, Liquid) to read at ~200×100 px anyway, so the shadow channel was carrying zero signal for four skins and one clear bug for the fifth. Drop `boxShadow` from the inline preview style. Each card still sells its skin via the display font + heading weight + tracking + border-radius — the surface treatment shows up on the real chrome the moment the user clicks. --- src/components/views/settings/SkinPickerCard.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/SkinPickerCard.tsx b/src/components/views/settings/SkinPickerCard.tsx index 46332292..b69c5402 100644 --- a/src/components/views/settings/SkinPickerCard.tsx +++ b/src/components/views/settings/SkinPickerCard.tsx @@ -92,12 +92,20 @@ export function SkinPickerCard() { // skin's actual tokens, not the active skin's. Using inline // styles also sidesteps having to round-trip through // tailwind / data-skin attribute fiddling for the preview. + // + // `shadowCard` is intentionally NOT applied here: Pulse's + // neon halo (`0 0 24px -4px var(--accent-500)`) leaks + // visibly past the button's overflow-hidden clip, and at + // ~200×100 px the other skins' shadows are too subtle to + // read anyway. The skin's identity is already carried by + // the display font + heading weight + tracking + radius; + // chrome-scale shadows belong on real surfaces, not on + // thumbnail previews. const previewStyle: React.CSSProperties = { fontFamily: preset.typography.display, fontWeight: preset.typography.headingWeight, letterSpacing: preset.typography.displayTracking, borderRadius: preset.radius.card, - boxShadow: preset.surface.shadowCard, }; return ( -

+

{t("about.hero.developedBy")}{" "} - WaveFlow Team + WaveFlow Team