Skip to content

Dark Mode Coverage Audit — Ideony Mobile

Dark Mode Coverage Audit — Ideony Mobile

Section titled “Dark Mode Coverage Audit — Ideony Mobile”

Date: 2026-04-20 Scope: apps/mobile/app/ (53 files) and apps/mobile/components/ (58 files)


MetricCount%
Screen files (app/**/*.tsx)53
Component files (components/**/*.tsx)58
Screens with any dark support (useThemeColors / darkColors / dark:)00%
Components with any dark support00%
Files using useColorScheme (NativeWind)2 (_layout.tsx, TabBar.tsx)3%
Files using dark: NativeWind class0 (in app/ + components/)0%

Root cause: Every screen and component imports the static colors object from @/lib/colors (the light palette) and passes values into StyleSheet.create(). useThemeColors() exists at lib/hooks/use-theme-colors.ts but is called by zero screens and zero components. The NativeWind dark: variant pathway requires darkMode: "class" — the class is never toggled programmatically, so dark: would also be inert even if used.


apps/mobile/lib/stores/theme.ts

export const useThemeStore = create<ThemeState>((set) => ({
preference: "system",
setPreference: (preference) => set({ preference }),
}));

No persist middleware, no AsyncStorage. Preference resets to "system" on every cold start.

apps/mobile/lib/hooks/use-theme-colors.ts reads NativeWind’s useColorScheme(). The Zustand preference is never forwarded to NativeWind’s setColorScheme(). Effect: the store preference has zero runtime effect on rendered colors.

apps/mobile/tailwind.config.ts sets darkMode: "class". No code anywhere calls NativeWind’s setColorScheme("dark") or puts a dark class on the root view. dark: variants compile but are permanently dead.


In app/ screens (inline hex, not via colors.*):

Section titled “In app/ screens (inline hex, not via colors.*):”
FileLiteral(s)
app/_layout.tsx13 Clerk appearance values: #B35F3B, #E5484D, #10B981, #F59E0B, #737371, #2B1E10, #8C7B6A, #FAF6EE, #F0EBE0, #DDD5C8
app/sos/[id]/tracking.tsxshadowColor: "#000"
app/review/[bookingId].tsxSUN_AMBER = "#E89059", DARK_INK = "#2B1E10", emoji colors #E5484D/#F5C842/#4A9EFF, color: "#FFFFFF" (×2)
app/booking/[id].tsxcolor: "#92400E"
app/(professional)/credentials.tsxcolor: "#FAF6EE"
app/(professional)/calendar.tsxselectedDayTextColor: "#FFFFFF"
app/(professional)/onboarding/portfolio.tsxcolor="#fff" (Trash icon)
app/chat/[bookingId].tsxcolor: isMe ? "#FAF6EE" : colors.text, color="#FAF6EE" (SendHorizontal icon)
app/(professional)/earnings.tsxcolor: "#FFFFFF"
app/(consumer)/triage.tsxAI_BUBBLE_BG = "#F5E6CB", color: "#2B1E10"
app/book/[professionalId].tsxcolor="#FFF" (CheckCircle2 icon)
FileLiteral(s)
components/credentials/TrustTierBadge.tsxbgColor: "#FFF4E6", textColor: "#B85C00", borderColor: "#E89059", iconColor: "#E89059"
components/credentials/AddCredentialSheet.tsxcolor="#fff" (ActivityIndicator), color: "#fff"
components/WelcomeTour.tsxshadowColor: "#000"
components/MediaAttachments.tsxcolor="#FFF" (X icon)
components/results/ProCard.tsxCategory colors "#7C6B52"/"#8B6914"/"#7A7A7A", shadowColor: "#8B4A2B"
components/results/CompareSheet.tsxshadowColor: "#000"
components/professional/HeroCarousel.tsxbackgroundColor: "#fff", color: "#fff"
components/ui/Badge.tsxtext: "#92400E", "#065F46" (×2), bg: "#DBEAFE", text: "#1E40AF", "#991B1B" (×2)
components/home/PromptCard.tsxshadowColor: "#2B1E10"

4. Light-Only colors.* Usage (Sole Palette — No Dark Equivalent)

Section titled “4. Light-Only colors.* Usage (Sole Palette — No Dark Equivalent)”

All 53 app screen files and 52 of 58 component files import colors (light) from @/lib/colors. None use useThemeColors() to switch between colors / darkColors. The full darkColors object exists in lib/colors.ts but is unreachable from any screen or component at runtime.

Highest-impact files (used as primary background/surface):

  • app/(consumer)/index.tsx — home screen
  • app/(consumer)/search.tsx
  • app/(professional)/dashboard.tsx
  • app/professional/[id].tsx — professional profile
  • app/booking/[id].tsx
  • app/chat/[bookingId].tsx
  • components/chrome/TabBar.tsx — uses const palette = colors (hardcoded; reads colorScheme from NativeWind but ignores it for palette selection)
  • components/chrome/Header.tsx

Zero dark: classes exist in any app/ or components/ file.

One exception within app: components/credentials/CredentialCard.tsx line 89 uses className="rounded-xl border bg-white p-4"bg-white with no dark:bg-* override.

dark: classes only appear in three lib files:

  • apps/mobile/lib/gluestack-config.ts
  • apps/mobile/lib/mapbox/style-urls.ts
  • apps/mobile/lib/mapbox/sole-palette.ts

Phase A spec: SOS flows must always render the dark palette regardless of system setting.

Current state: NOT enforced anywhere.

FilePalette usedDark enforcement
app/sos/_layout.tsxcolors.background (light cream)None
app/sos/index.tsxcolors.* throughoutNone
app/sos/[id]/countdown.tsxcolors.* throughoutNone
app/sos/[id]/tracking.tsxcolors.* + shadowColor: "#000"None
app/sos/[id]/cancelled.tsxcolors.*None
app/sos/[id]/complete.tsxcolors.*None
components/sos/SOSButton.tsxcolors.sos, colors.textInverse, colors.sosLight (light)None
components/sos/DispatchStatusBar.tsxcolors.sos, colors.accent, colors.success (light)None
components/sos/TrackingMap.tsxstyleURL={MAPBOX_DARK_STYLE} (dark-v11)Map style dark only
components/sos/CandidateCard.tsxcolors.* (light)None
components/sos/CountdownRing.tsxcolors.* (light)None

TrackingMap hardcodes "mapbox://styles/mapbox/dark-v11" — uses a generic Mapbox dark style instead of the custom MAPBOX_SOLE_DARK URL from lib/mapbox/style-urls.ts.


All Phosphor (phosphor-react-native) and Lucide (lucide-react-native) icon color= props consume colors.* (light palette). No icon reads from useThemeColors().

Tab bar icons in app/(consumer)/_layout.tsx receive color via the tabBarIcon callback — sourced from TabBar.tsx which computes iconColor = isFocused ? palette.primary : palette.textTertiary where palette = colors (hardcoded light).

Notable fixed-hex icon colors in screens/components (not via colors.*):

  • app/book/[professionalId].tsx: <CheckCircle2 color="#FFF" />
  • app/chat/[bookingId].tsx: <SendHorizontal color="#FAF6EE" />
  • app/(professional)/onboarding/portfolio.tsx: <Trash color="#fff" />
  • components/MediaAttachments.tsx: <X color="#FFF" />

Root app/_layout.tsx:

<StatusBar style={colorScheme === "dark" ? "light" : "dark"} />

Correct — dynamic. No other StatusBar instances in non-layout files.


packages/design-tokens/src/index.ts exports only the light Sole palette. No dark token scale.

darkColors exists only in apps/mobile/lib/colors.ts as hardcoded hex values with no token references. Moving dark tokens into @ideony/design-tokens is a prerequisite for multi-package dark mode consistency.


apps/mobile/app.json:

{ "backgroundColor": "#FAF6EE" }

Light cream only. No dark splash variant. iOS/Android do not support per-scheme splash background via Expo config — requires native splash screen swap workaround.


Two dark map styles exist and are well-defined:

  • MAPBOX_SOLE_DARK at lib/mapbox/style-urls.ts — custom brand dark style
  • SOLE_DARK_CONFIG at lib/mapbox/sole-palette.ts — Standard style runtime config

Neither is wired to system color scheme in any map component. TrackingMap hardcodes a non-Sole dark style (dark-v11). MiniMap.tsx and MapAffordanceStrip.tsx (consumer home) both import colors light palette — map style URLs not checked but no colorScheme branching visible.


apps/mobile/app/_layout.tsx lines 101–160: 13 hardcoded light-palette hex values passed to Clerk’s appearance prop. No dark conditional. Clerk’s appearance API accepts object-level variants — a dark theme object would need to be added.


  1. Wire Zustand → NativeWind: call setColorScheme(preference) in useThemeStore.setPreference + on hydration
  2. Add AsyncStorage persistence to useThemeStore
  3. Replace colors imports with useThemeColors() in all screens and components (51 app files, 52 component files)
  4. SOS dark enforcement: use darkColors unconditionally in all app/sos/** and components/sos/**
  5. Export dark tokens from @ideony/design-tokens
  6. Fix Clerk appearance to branch on color scheme
  7. Fix TrackingMap to use MAPBOX_SOLE_DARK instead of generic dark-v11
  8. CredentialCard bg-whitebg-white dark:bg-surface
  9. Splash: add dark splash workaround (native splash swap on hydration)