From a8563b3fcb3ad17e62c2929a5d83521588cf20ee Mon Sep 17 00:00:00 2001 From: Dylan Audius Date: Mon, 24 Aug 2026 16:48:12 -0700 Subject: [PATCH] fix(mobile): make the Android glass surface fully opaque MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android has no backdrop blur, so `GlassSurface` fell back to a 0.94 tint to keep a hint of translucency. Verifying on a Pixel 8 Pro showed that only works in light mode. Translucency reads as frost when something blurs what shows through; with no blur, whatever bleeds through keeps its edges and reads as legible ghost text sitting on the header. The 6% bleed is ~8% relative contrast on a light surface (RGB 248) but ~93% on a dark one (RGB 14) — 6% of near-white content over near-black nearly doubles the luminance. In dark mode track titles, artists, durations and play counts were plainly readable behind the header. No single alpha works for both themes, so Android now trades the hint of translucency for a clean surface, matching the `ProfileNavOverlay` fallback this was meant to follow in the first place. Content still slides under the header — it just isn't see-through. iOS is unchanged and keeps its real blur. Verified on the Android emulator in dark mode with real content behind the header; iOS untouched. Co-Authored-By: Claude Opus 5 --- .../components/core/Screen/GlassSurface.tsx | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/mobile/src/components/core/Screen/GlassSurface.tsx b/packages/mobile/src/components/core/Screen/GlassSurface.tsx index 6b2022ff106..f7a77897283 100644 --- a/packages/mobile/src/components/core/Screen/GlassSurface.tsx +++ b/packages/mobile/src/components/core/Screen/GlassSurface.tsx @@ -21,14 +21,22 @@ import { isDarkTheme, useThemeColors, useThemeVariant } from 'app/utils/theme' const IOS_TINT_OPACITY = 0.72 /** - * Android does not get a real backdrop blur. `@react-native-community/blur`'s - * Android implementation is expensive enough to drop frames on a surface that - * is composited on every scroll frame, and the existing app-wide precedent - * (ProfileNavOverlay) already falls back to a solid fill there. We use a high - * -opacity tint instead: content still slides under the header, it just isn't - * blurred while it does. + * Android does not get a real backdrop blur — `@react-native-community/blur`'s + * Android implementation is expensive enough to drop frames on a surface + * composited on every scroll frame — so the surface is fully opaque there, + * matching the existing `ProfileNavOverlay` fallback. + * + * It is opaque rather than *nearly* opaque on purpose. Translucency only reads + * as frost when something blurs what shows through; with no blur, whatever + * bleeds through keeps its edges and reads as legible ghost text sitting on + * top of the header. A previous 0.94 looked acceptable in light mode (~8% + * relative contrast) but broke badly in dark: 6% of near-white content over a + * near-black surface is a ~93% luminance jump, leaving track titles and play + * counts clearly readable behind the header. Any single alpha that suits one + * theme is wrong for the other, so Android trades the hint of translucency for + * a clean surface. Content still slides under it — it just isn't see-through. */ -const ANDROID_TINT_OPACITY = 0.94 +const ANDROID_TINT_OPACITY = 1 /** * Scroll distance (px) over which the bottom edge fades from invisible to