Styling NativeBase theme based on color mode
View more posts
August 10, 2022 โ€ข 3 minute read

Styling NativeBase theme based on color mode

Ankit Tailor
Software Engineer
Modern applications need to support multiple color modes, including an easy switch between light and dark mode. This article is the complete guide to creating color modes in React Native apps with toggle features.
ย 
What we will cover โคต๏ธ
  1. How to set the initial color mode
  1. System-based color mode
  1. Getting system color mode using React Native
  1. Getting color mode using NativeBase
  1. Hooks and pseudo props to achieve color mode
  1. Toggling color mode
  1. Demo till now
  1. Persisting color mode

How to set the initial color mode

๐Ÿ‘‰ย You can extend the default theme with config in NativeBaseProvider. The default color mode is light.
๐Ÿ‘‰ To set the initial color mode, pass initialColorMode in the config object. It will take the values assigned for light and dark. The initial color mode of the app will be the one passed as initialColorMode.
ย 
import React from "react";
import { NativeBaseProvider, extendTheme } from "native-base";

export function App({ children }) {
	const config = {
		initialColorMode: "dark",  // initial color mode 
	}

	const extendedTheme = extendTheme({ config })

	return (
		<NativeBaseProvider theme={extendedTheme} >
			{children}
		</NativeBaseProvider>
	)
}
ย 

System-based color mode

๐Ÿ‘‰ย The useSystemColorMode prop sets the app's color mode based on the system. It uses the boolean value.
๐Ÿ‘‰ If useSystemColorMode is true, then the initial color mode will be the system color mode. Else, it will be light mode.
ย 
import React from "react";
import { NativeBaseProvider, extendTheme } from "native-base";

export function App({ children }) {
	const config = {
		useSystemColorMode: true,   // Default system color mode
	}

	const extendedTheme = extendTheme({ config })

	return (
		<NativeBaseProvider theme={extendedTheme} >
			{children}
		</NativeBaseProvider>
	)
}
ย 

Getting system color mode using React Native

๐Ÿ‘‰ The Appearance module provides information about the user's appearance preferences.
๐Ÿ‘‰ You can get the desired color scheme using getColorScheme.
ย 
import { Appearance } from 'react-native';
const colorScheme = Appearance.getColorScheme();
console.log(colorScheme, 'color-scheme');
  if (colorScheme === 'dark') {
    // Use dark color scheme
  }

Getting color mode using NativeBase

๐Ÿ‘‰ NativeBase provides a hook to get the desired color mode.
ย 
const { colorMode } = useColorMode();  // light or dark
๐Ÿ‘‰ย The applied scheme will be light or dark based on the current color mode.

Hooks and pseudo props for color mode

๐Ÿ‘‰ย NativeBase provides the following props to get the format you want.
  1. useColorMode
  1. useColorModeValue
  1. _light
  1. _dark
Weโ€™ve explained what they are below โคต๏ธ

useColorMode

This hook provides access to the current colorMode of the app and toggleColorMode.
const Example = () => {
  const { colorMode, toggleColorMode } = useColorMode();
  return (
    <Center
      flex={1}
      bg={colorMode === "light" ? "coolGray.50" : "coolGray.800"}
    >
      <Heading color={colorMode === "light" ? "coolGray.800" : "coolGray.50"}>
        {`Color mode is toggled to ${colorMode}.`}
      </Heading>
      <Pressable mt="10" onPress={toggleColorMode}>
        {colorMode === "light" ? (
          <MoonIcon color="coolGray.800" size="6" />
        ) : (
          <SunIcon color="coolGray.50" size="6" />
        )}
      </Pressable>
    </Center>
  );
};
๐Ÿ‘‰ In the above snippet, colorMode will be light or dark based on the current color mode. You can use the toggleColorMode function anywhere in the app to switch between the two modes.
ย 
notion image
ย 

useColorModeValue

This hook takes two arguments: values in light and values in dark.
ย 
const Example = () => {
  const { colorMode, toggleColorMode } = useColorMode()
  const bg = useColorModeValue('coolGray.50', 'coolGray.800')
  const color = useColorModeValue('coolGray.800', 'coolGray.50')
  const icon = useColorModeValue(
    <MoonIcon color="coolGray.800" size="6" />,
    <SunIcon color="coolGray.50" size="6" />
  )

  return (
    <Center flex={1} bg={bg}>
      <Heading color={color}>
        {`Color mode is toggled to ${colorMode}.`}
      </Heading>
      <Pressable mt="10" onPress={toggleColorMode}>
        {icon}
      </Pressable>
    </Center>
  )
}
๐Ÿ‘‰ In the above snippet, useColorModeValue hook is taking light and dark mode values respectively.
ย 
notion image
ย 

_light & _dark

๐Ÿ‘‰ Styles passed in _light & _dark will be applied in their respective modes.
ย 
import React from 'react';
import { Icon, useColorMode, Pressable, Center, Heading } from 'native-base';
import { Feather } from '@expo/vector-icons';

export const Example = () => {
  const { colorMode, toggleColorMode } = useColorMode();

  return (
    <Center
      flex={1}
      w="full"
      _light={{ bg: 'coolGray.50' }}
      _dark={{ bg: 'coolGray.800' }}
    >
      <Heading
        _light={{ color: 'coolGray.800' }}
        _dark={{ color: 'coolGray.50' }}
      >
        {`Color mode is toggled to ${colorMode}.`}
      </Heading>
      <Pressable mt="10" onPress={toggleColorMode}>
        <Icon as={Feather} _light={{ name: 'moon' }} _dark={{ name: 'sun' }} />
      </Pressable>
    </Center>
  );
};
ย 
By default, NativeBase components are dark mode enabled.
ย 
Note: Itโ€™s recommended to use _light and _dark props, if you want to useย useColorModeValue hook, you can use it at top of the component.

Toggling color modes

๐Ÿ‘‰ You can use useColorMode hook for toggling. It provides a toggleColorMode function that can be used to switch between the two modes.
ย 
const { toggleColorMode } = useColorMode();
ย 
๐ŸŽ‰ย And thatโ€™s how we use different color modes and toggle between them using NativeBase.
ย 

Summary and Demo

๐Ÿ‘‰ย Itโ€™s time to see everything in action. To access the source code of the demo CLICK HERE. ๐ŸŽ‰๐ŸŽ‰
๐Ÿ‘‰ย In the above demo code, the initial mode will be the system color mode.
๐Ÿ‘‰ย Theย useColorMode hooks get the current color mode and toggle color mode.
๐Ÿ‘‰ย _light and _dark pseudo props apply to style based on color mode.
ย 
But what about color mode persistence? ๐Ÿค”๐Ÿค”
Here is how to use them for native and web.

Persisting color mode

๐Ÿ‘‰ You can keep a color mode persistent by defining colorModeManager of type StorageManager in NativeBaseProvider. This will retain color mode even if the page is refreshed.

For Native

๐Ÿ‘‰ Use react-native-async-storage in native apps. It is asynchronous and a key-value storage for React Native applications.
ย 
import React from 'react';
import { NativeBaseProvider, StorageManager, ColorMode } from 'native-base';
import AsyncStorage from '@react-native-async-storage/async-storage';

const colorModeManager: StorageManager = {
  get: async () => {
    try {
      let val = await AsyncStorage.getItem('@color-mode');
      return val === 'dark' ? 'dark' : 'light';
    } catch (e) {
      return 'light';
    }
  },
  set: async (value: ColorMode) => {
    try {
      await AsyncStorage.setItem('@color-mode', value);
    } catch (e) {
      console.log(e);
    }
  },
};
export default function () {
  return (
    // pass it to NativeBaseProvider
    <NativeBaseProvider colorModeManager={colorModeManager}>
      {children}
    </NativeBaseProvider>
  );
}
ย 

For web

๐Ÿ‘‰ Use localStorage to store color mode in the web browser. It is a read-only property of the window interface. This provides access to a storage object for the document's origin. The data stored is saved across browser sessions.
ย 
import React from 'react';
import { ColorMode, NativeBaseProvider, StorageManager } from 'native-base';
const colorModeManager: StorageManager = {
  get: async () => {
    let val = localStorage.getItem('@color-mode');
    return val === 'dark' ? 'dark' : 'light';
  },
  set: async (value: ColorMode) => {
    let strValue = value ? value.toString() : '';
    localStorage.setItem('@color-mode', strValue);
  },
};

export default function () {
  return (
    <NativeBaseProvider colorModeManager={colorModeManager}>
      {children}
    </NativeBaseProvider>
  );
}
ย 
If you want to explore more, here are some examples of applications that were built using NativeBase. Check them out here ๐Ÿ”—ย https://madewithnativebase.com/
ย 
Till next time then, ciao! ๐Ÿ‘‹๐Ÿป