ryer.io

Two Theme Bugs: iOS Won't Inherit, and Logout Resets Too Early

TL;DR

  • Dark mode contrast broke in the date picker’s month selector on iOS after upgrading 5.02 to 5.13.
  • Android inherits system text colour automatically; iOS needs it assigned explicitly, and ours wasn’t.
  • Separately, logging out caused a UI flicker as the theme reverted to default blue mid-transition.
  • Cause: a successful logout resets state booleans and takes the theme palette to undefined with them.
  • Fixed by hardcoding the onboarding screens’ theme so transitions have something stable to land on.

Two theming bugs today. Different symptoms, and they rhyme: in both cases a colour was left undefined at a moment when something needed to render.

Bug one: dark mode contrast on iOS

Testing the React Native Date Picker upgrade from 5.02 to 5.13, the month selector in the monthly report section became barely readable in dark mode on iOS. Android was fine.

The month selector is a custom component, and it wasn’t responding to theme changes at all. The reason Android looked correct is that it leverages the Android system’s text colour state and picks up the right value for free. iOS requires an explicit assignment, and we never made one — so on iOS the text kept a colour chosen for a light background while the background went dark.

The platform difference is the whole lesson here. Android’s default masked a missing definition, so the bug only existed on the platform that doesn’t guess for you.

The fix is a stateful iosTextColor updated on focus and theme change, driven by system theme detection. I verified it by switching between light and dark repeatedly and watching the typography follow.

Going forward this becomes standard: a conditional text colour based on system settings, rather than trusting one platform’s default to cover both.

Bug two: theme flicker on logout

Logging out produced a visible flicker — the user state reset to initial before the UI finished transitioning to the onboarding screens, and the theme colour reverted to default partway through.

My first fix didn’t work. I extended a logout function from the app’s data context so the parent navigator could call it once navigation completed, on the logic that resetting state after navigation would avoid the premature shift. The flicker persisted. The reset was still visibly landing before navigation genuinely finished, which made the whole approach moot.

The real cause was in the theme context provider. A successful logout call triggers a useEffect that resets the booleans governing our UI states — and inadvertently resets the current theme palette to undefined along with them. Undefined falls back to the default blue. That fallback is the flicker.

The fix was to hardcode the onboarding screens’ theme colour, so state transitions always have a consistent, defined appearance to land on regardless of what theme the user had selected before logging out. The boolean reset stays intact, because it’s doing necessary work; only the theme is insulated from it.

While I was in there I consolidated the colour definitions into the theme context rather than scattering them across basic colours, aligned them with device-specific schemes, and checked components like pagination for stray theme dependencies that bypassed the palette.

The common thread

Both bugs are the same shape at different scales. Something needed a colour, nothing had explicitly defined one for that context, and a fallback filled the gap — silently on iOS, visibly during logout. Defining the value explicitly at the boundary fixed both.

An unrelated interruption partway through: news of Ozzy Osbourne’s death. Chaos and brilliance in one life, which is not the worst description of a day spent chasing colours through a state machine.