Skip to content

#7 Dark mode for both apps - #40

Open
arfi30 wants to merge 1 commit into
wncc:mainfrom
arfi30:issue-007-dark-mode
Open

arfi30 wants to merge 1 commit into
wncc:mainfrom
arfi30:issue-007-dark-mode

Conversation

@arfi30

@arfi30 arfi30 commented Oct 27, 2026

Copy link
Copy Markdown

Closes #7

What changed

Theme

  • src/lib/theme.ts: a dark palette next to the light one, same keys, and paletteFor(scheme).
  • ui.tsx: useTheme() on top of useColorScheme(), and themed((t) => StyleSheet.create({…})), which gives each file a useStyles() hook. Screens keep their StyleSheet.create, but the styles are rebuilt when the phone's theme changes, so the app switches straight away. The fixed colors export is removed, so TypeScript made sure every screen moved over (login, name, rider home, ride, history, driver home, vehicle, trip).
  • Status bar is auto; the stack headers ("Your rides", "Your vehicle", "Rides & earnings") and screen backgrounds are themed in the three layouts, so nothing flashes white between screens.

Map (mapPage.ts, RideMap*.tsx)

  • Dark mode uses a CSS filter on the tile pane (invert + hue-rotate(180deg), so water stays blue and parks green) and a dark page background, so the map never flashes white while tiles load.
  • The route, approach and placeholder lines get colours that show on dark tiles (route is near-white instead of near-black). Pickup/drop/driver markers keep their colours: they already have a white ring and read fine on both.
  • setDark() restyles the open map in place when the theme flips: no reload, no jump.

Tests

  • theme.test.ts: both palettes define the same colours; in both, text, muted text, errors and button labels meet WCAG AA (4.5:1).
  • mapPage.test.ts: starts dark when asked; setDark() toggles body.dark and recolours the route without moving the map; the page HTML carries the tile filter; darkScript() is valid JS and safe before the page is ready.
  • e2e/run_e2e.py --dark: the browser robot plays the whole ride with both phones in dark mode. 11/11 steps pass in light and in dark (documented in docs/TESTING.md).
  • Live switch checked on the web build: flipping prefers-color-scheme on an open rider home switches the app and the map without a reload.
  • python test_all.py --quick passes: typecheck, lint, 38 Jest tests, Python tests unchanged.

Screenshots (light / dark)

Login · Rider fares · Rider ride · Driver trip · Vehicle · Rides & earnings

dark-4-driver-trip dark-5-vehicle dark-6-earnings light-1-login light-2-rider-fares light-3-rider-ride light-4-driver-trip light-5-vehicle light-6-earnings dark-1-login dark-2-rider-fares dark-3-rider-ride

Both apps follow the phone's light/dark setting. A dark palette sits next
to the light one (src/lib/theme.ts); useTheme() picks one from
useColorScheme(), and themed() turns a palette -> StyleSheet function into
a useStyles() hook, so screens keep their StyleSheet.create but re-evaluate
when the theme flips. The fixed `colors` export is gone, which is what made
every screen migrate.

Map: a `dark` option inverts the raster tiles with a CSS filter (hue put
back so water stays blue), gives the page a dark background so it never
flashes white, and recolours the route and approach lines so they show on
dark tiles. setDark() restyles the open map in place; no reload, no jump.

Status bar is `auto`; stack headers and screen backgrounds are themed in
the three layouts.

Tests: palette parity and WCAG AA contrast for text, muted text, errors
and button labels in both palettes; the map script's dark start, live
switch and line colours; the html carries the tile filter. The e2e robot
takes --dark, which plays the whole ride with both phones in dark mode:
11/11 steps pass in both modes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dark mode for both apps

1 participant