Skip to content

Appearance Settings

The Settings tab lets a senior shape how every screen reads: a color theme (System, Light, or Dark), a text size (Large or Extra large), and a font (Sans-serif, Serif, or Monospace). The choices apply to every presentation of text in the app — screen content, buttons, captions, text inputs, tab bar labels, and navigation headers — and they are saved on the device, so the app opens the way it was left.

The choices

Setting Options Default What it does
Color theme System, Light, Dark System Forces the light or dark palette, or follows the OS setting
Text size Large, Extra large Large Extra large multiplies the whole type scale by 1.25
Font Sans-serif, Serif, Monospace Sans-serif Switches every text surface to a platform system font (Georgia and Menlo on iOS, serif and monospace on Android)

Each font option's label is rendered in the font it selects, so the choice is visible before it is made.

Two deliberate compositions:

  • Text size composes with OS font scaling. The multiplier applies to the base type scale and Dynamic Type still applies on top; the app never sets allowFontScaling={false}.
  • Video captions stay proportionally larger. The caption enlargement in the video quiz multiplies the chosen text size instead of replacing it.

How it works

  • settings-storage.ts persists the three choices as one JSON value in AsyncStorage under a versioned key. Anything unreadable falls back to the defaults.
  • appearance.tsx provides AppearanceProvider (mounted once in the root layout), useAppearance() for the values and persisting setters, and useEffectiveColorScheme() — the user's theme, or the OS scheme while the theme is System. The provider holds back its children until the stored settings are in state, so launch never flashes the wrong theme before the load resolves. Without a provider the hooks serve the defaults, which is why existing tests can render screens bare.
  • typography.ts holds the Daybreak tokens behind the feature: fontSizeMultipliers, fontFamilies, and resolveTypeStyle(variant, fontSize, fontFamily). At the defaults it returns exactly the base type scale, so the standard look never drifts.
  • ThemedText resolves its style through resolveTypeStyle, which is how the settings reach nearly all text. The exceptions are styled directly: the pattern-builder TextInput (including its keyboardAppearance), video captions, tab bar labels (tabBarLabelStyle), and stack headers (headerTitleStyle, headerBackTitleStyle). Navigation text styles only set the keys that deviate from the platform defaults, so untouched settings render exactly the stock chrome.

Accessibility

  • Each setting is a radiogroup of large tap targets; every option is a radio with accessibilityState.checked and a hint like "Sets color theme to Dark".
  • Selection is carried by a checkmark and the border, never by color alone.
  • The option rows wrap, so every option stays reachable at the largest text settings.
  • Both palettes carry measured contrast ratios (see colors.ts), and the theme override drives the navigation theme and status bar too, so chrome and content never disagree.