React Native course ยท Module 2: Lists and styles

StatusBar and Theming

3 min read ยท
In this lesson2

Control the appearance of the status bar and create a theme system for your application.

StatusBar

import { SafeAreaView, View, Text, StyleSheet, StatusBar, Pressable } from 'react-native';
import { useState } from 'react';

export default function StatusBarExample() {
  const [isDark, setIsDark] = useState(true);

  return (
    <SafeAreaView style={[
      styles.container,
      { backgroundColor: isDark ? '#1a5276' : '#ecf0f1' }
    ]}>
      <StatusBar
        barStyle={isDark ? 'light-content' : 'dark-content'}
        backgroundColor={isDark ? '#1a5276' : '#ecf0f1'}
        animated={true}
      />

      <View style={styles.content}>
        <Text style={[styles.title, { color: isDark ? '#fff' : '#2c3e50' }]}>
          Status Bar Demo
        </Text>

        <Pressable
          style={[styles.button, { backgroundColor: isDark ? '#2980b9' : '#3498db' }]}
          onPress={() => setIsDark(!isDark)}
        >
          <Text style={styles.buttonText}>
            Switch to {isDark ? 'light' : 'dark'} theme
          </Text>
        </Pressable>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  content: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 30,
  },
  button: {
    paddingVertical: 14,
    paddingHorizontal: 24,
    borderRadius: 8,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

Theme System with Context

// context/ThemeContext.tsx
import { createContext, useContext, useState, ReactNode } from 'react';

interface Theme {
  dark: boolean;
  colors: {
    background: string;
    card: string;
    text: string;
    textSecondary: string;
    primary: string;
    border: string;
  };
}

const lightTheme: Theme = {
  dark: false,
  colors: {
    background: '#f5f6fa',
    card: '#ffffff',
    text: '#2c3e50',
    textSecondary: '#7f8c8d',
    primary: '#3498db',
    border: '#dcdde1',
  },
};

const darkTheme: Theme = {
  dark: true,
  colors: {
    background: '#1a5276',
    card: '#2c3e50',
    text: '#ffffff',
    textSecondary: '#bdc3c7',
    primary: '#3498db',
    border: '#34495e',
  },
};

interface ThemeContextType {
  theme: Theme;
  toggleTheme: () => void;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [isDark, setIsDark] = useState(true);

  const theme = isDark ? darkTheme : lightTheme;

  const toggleTheme = () => setIsDark(!isDark);

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return context;
}
// components/ThemedCard.tsx
import { View, Text, StyleSheet } from 'react-native';
import { useTheme } from '../context/ThemeContext';

interface ThemedCardProps {
  title: string;
  description: string;
}

export default function ThemedCard({ title, description }: ThemedCardProps) {
  const { theme } = useTheme();

  return (
    <View style={[styles.card, { backgroundColor: theme.colors.card }]}>
      <Text style={[styles.title, { color: theme.colors.text }]}>
        {title}
      </Text>
      <Text style={[styles.description, { color: theme.colors.textSecondary }]}>
        {description}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: {
    padding: 16,
    borderRadius: 12,
    marginBottom: 12,
  },
  title: {
    fontSize: 18,
    fontWeight: '600',
    marginBottom: 4,
  },
  description: {
    fontSize: 14,
  },
});
// App.tsx
import { SafeAreaView, View, StyleSheet, StatusBar, Pressable, Text } from 'react-native';
import { ThemeProvider, useTheme } from './context/ThemeContext';
import ThemedCard from './components/ThemedCard';

function HomeScreen() {
  const { theme, toggleTheme } = useTheme();

  return (
    <SafeAreaView style={[styles.container, { backgroundColor: theme.colors.background }]}>
      <StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />

      <View style={styles.content}>
        <ThemedCard
          title="Treasure of Atlantis"
          description="A legendary jewel from the ocean depths"
        />
        <ThemedCard
          title="Poseidon's Trident"
          description="Weapon of the ruler of the seas"
        />

        <Pressable
          style={[styles.button, { backgroundColor: theme.colors.primary }]}
          onPress={toggleTheme}
        >
          <Text style={styles.buttonText}>
            {theme.dark ? 'Light theme' : 'Dark theme'}
          </Text>
        </Pressable>
      </View>
    </SafeAreaView>
  );
}

export default function App() {
  return (
    <ThemeProvider>
      <HomeScreen />
    </ThemeProvider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  content: {
    flex: 1,
    padding: 20,
  },
  button: {
    marginTop: 20,
    paddingVertical: 14,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

Congratulations! You have mastered advanced components and styling in React Native!

Code for this lesson: App.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';
import { SafeAreaView, View, Text, Pressable, StyleSheet } from 'react-native';

const lightTheme = {
  dark: false,
  background: '#f5f6fa',
  card: '#ffffff',
  text: '#2c3e50',
};

const darkTheme = {
  dark: true,
  background: '#1a5276',
  card: '#2c3e50',
  text: '#ffffff',
};

const ThemeContext = createContext({ theme: darkTheme, toggleTheme: () => {} });

function ThemeProvider({ children }: { children: ReactNode }) {
  const [isDark, setIsDark] = useState(true);

  // TODO: pick the theme based on the isDark state.
  //   const theme = isDark ? darkTheme : lightTheme;
  const theme = darkTheme;

  // TODO: create a toggleTheme function that flips isDark.
  //   const toggleTheme = () => setIsDark(!isDark);
  const toggleTheme = () => {};

  // TODO: pass { theme, toggleTheme } to the Provider's value prop.
  return (
    <ThemeContext.Provider value={{ theme: darkTheme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

function HomeScreen() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
      <View style={[styles.card, { backgroundColor: theme.card }]}>
        <Text style={[styles.text, { color: theme.text }]}>Treasure of Atlantis</Text>
      </View>
      <Pressable style={styles.button} onPress={toggleTheme}>
        <Text style={styles.buttonText}>
          {theme.dark ? 'Light theme' : 'Dark theme'}
        </Text>
      </Pressable>
    </SafeAreaView>
  );
}

export default function App() {
  return (
    <ThemeProvider>
      <HomeScreen />
    </ThemeProvider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  card: {
    padding: 16,
    borderRadius: 12,
    marginBottom: 20,
  },
  text: {
    fontSize: 18,
    fontWeight: '600',
  },
  button: {
    paddingVertical: 14,
    borderRadius: 8,
    alignItems: 'center',
    backgroundColor: '#3498db',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Which StatusBar barStyle value shows light icons (for a dark background)?

  2. 2. What does the useColorScheme() hook return?

Hands-on tasks in the game

  • Vertical ordering

    Arrange the steps of creating a theme system with Context API:

  • Code editor

    Complete the ThemeProvider and ThemeContext code.

Useful articles