Color Theme Matters

Why

  • Consistency: If you reference Colors.primary everywhere rather than hard‐coding #4A90E2, you guarantee uniform look.
  • Maintainability: When your designer says “Change primary from blue to purple,” you change one file instead of hunting through hundreds of styles.
  • Light/Dark Mode: By defining both a “light” palette and a “dark” palette, your UI can automatically adapt when the user switches their device theme (iOS or Android).
  • Accessibility & Contrast: A well‐designed theme makes it easier to ensure your text has enough contrast against your backgrounds in both modes.
  • Semantic Usage: You think “This is a primary button,” “This is a background surface,” “This is error text,” etc. rather than “This is #E53935,” which clarifies intent.

2. Building Blocks: Color “Slots” or Tokens

Most apps follow a pattern similar to Material Design’s color roles. You can simplify or expand as needed, but here is a common set:

type ThemeColors = {
  /** Primary brand color (buttons, links, active elements) */
  primary: string

  /** Secondary accent color (for highlights, toggles, UI accents) */
  secondary: string

  /** Background color of app screens */
  background: string

  /** Surface color: card backgrounds, sheets, etc. */
  surface: string

  /** Default text color on a “surface” background */
  text: string

  /** Subheading or secondary text (less emphasis) */
  textSecondary: string

  /** Borders and dividers */
  border: string

  /** Error states (form errors, destructive buttons) */
  error: string

  /** Success states (toast messages, success badges) */
  success: string

  /** Warning states (alerts) */
  warning: string

  /** Disabled / inactive elements */
  disabled: string
}

Why These Tokens?

  • primary: Used for your main call‐to‐action, interactive elements, and highlights.
  • secondary: A contrasting accent you can use sparingly (for example, in badges or secondary buttons).
  • background: The “canvas” behind the entire screen (often a very light gray in light mode, or near‐black in dark mode).
  • surface: Used for “cards,” “sheets,” “modals,” anything that sits on top of the background.
  • text & textSecondary: Ensure your main text is high‐contrast, while secondary text can be a bit lighter.
  • border: For hairline dividers, input outlines, separators between list items.
  • error, success, warning: Dedicated semantic colors for form validation, status badges, or snackbars.
  • disabled: A semi‐transparent or low‐contrast color to show that a button or input is not interactive.

3. Coding the Theme: Light & Dark Palettes

Create a file app/constants/Colors.ts (or app/theme/Colors.ts). In there, define two objects—light and dark—that conform to ThemeColors.

// app/constants/Colors.ts

export interface ThemeColors {
  primary: string
  secondary: string
  background: string
  surface: string
  text: string
  textSecondary: string
  border: string
  error: string
  success: string
  warning: string
  disabled: string
}

// A sample Light Theme palette
export const light: ThemeColors = {
  primary: '#4A90E2',        // a pleasant medium‐blue
  secondary: '#D81B60',      // a striking magenta accent
  background: '#F7F7F7',     // very light gray
  surface: '#FFFFFF',        // pure white cards/sheets
  text: '#212121',           // nearly black, high contrast on white
  textSecondary: '#666666',  // mid‐gray for subheadings
  border: '#E0E0E0',         // light gray border
  error: '#E53935',          // red
  success: '#43A047',        // green
  warning: '#FB8C00',        // orange
  disabled: '#BDBDBD',       // light gray for disabled
}

// A sample Dark Theme palette
export const dark: ThemeColors = {
  primary: '#64B5F6',        // lighter blue for dark backgrounds
  secondary: '#F48FB1',      // lighter accent
  background: '#121212',     // near‐black background
  surface: '#1E1E1E',        // dark gray for cards/sheets
  text: '#FFFFFF',           // white text on dark surfaces
  textSecondary: '#A0A0A0',  // light‐gray for secondary text
  border: '#272727',         // slightly lighter than surface
  error: '#EF5350',          // red
  success: '#66BB6A',        // green
  warning: '#FFA726',        // orange
  disabled: '#555555',       // gray for disabled controls
}

// A small helper to pick the right theme
export const Colors = { light, dark }
  • Notice how the dark palette always picks slightly lighter versions (so that buttons/pop‐ups stand out on a near‐black background).


Click here to share this article with your friends on X if you liked it.