diff --git a/docs/pages/8.theming-with-react-navigation.md b/docs/pages/8.theming-with-react-navigation.md index c2a94389eb..402ea5becc 100644 --- a/docs/pages/8.theming-with-react-navigation.md +++ b/docs/pages/8.theming-with-react-navigation.md @@ -9,6 +9,51 @@ In this guide we will look into how to apply theming for an application using Re Offering different theme options, especially dark/light ones, becomes increasingly a standard requirement of the modern mobile application. Fortunately, both React Navigation and React Native Paper support configurable theming out-of-the-box. But how to make them work together? +## Themes adaptation + +### Material Design 2 + +Fortunately, in Material Design 2, both React Navigation and React Native Paper offer very similar API when it comes to theming and theme color structure. It's possible to import them in light and dark variants from both. + +```js +import { + DarkTheme as NavigationDarkTheme, + DefaultTheme as NavigationDefaultTheme, +} from '@react-navigation/native'; + +import { + MD2LightTheme, + MD2DarkTheme, +} from 'react-native-paper'; +``` + +### Material Design 3 + +From v5, React Native Paper theme colors structure is following the Material Design 3 (known as Material You) colors system, which differs significantly from both previous Paper's theme and React Navigation theme. + +However, to simplify adapting React Navigation theme to the latest Paper's colors structure, it's worth using a utility called `adaptNavigationTheme` – it accepts navigation compliant themes in both modes and returns their equivalents adjusted to Material Design 3. + +```ts +import { + DarkTheme as NavigationDarkTheme, + DefaultTheme as NavigationDefaultTheme, +} from '@react-navigation/native'; + +const { LightTheme, DarkTheme } = adaptNavigationTheme({ + lightTheme: NavigationDefaultTheme, + darkTheme: NavigationDarkTheme, +}); +``` + +Library exports also Material Design 3 themes in both modes: + +```js +import { + MD3LightTheme, + MD3DarkTheme, +} from 'react-native-paper'; +``` + ## Combining theme objects Both libraries require a wrapper to be used at the entry point of the application. @@ -71,9 +116,7 @@ export default function App() { } ``` -Fortunately, both React Navigation and React Native Paper offer very similar API when it comes to theming. It's possible to import default themes in light and dark variants from both. -React Navigation and React Native Paper use the same name for default themes - `DefaultTheme` and `DarkTheme`, so we need to alias them at the imports. Our goal here is to combine those two themes, so that we could control the theme for the entire application from a single place. @@ -83,6 +126,8 @@ To make things easier we can use [deepmerge](https://www.npmjs.com/package/deepm yarn add deepmerge ``` +### Material Design 2 + ```js import { NavigationContainer, @@ -90,37 +135,87 @@ import { DefaultTheme as NavigationDefaultTheme, } from '@react-navigation/native'; import { - DarkTheme as PaperDarkTheme, - DefaultTheme as PaperDefaultTheme, - Provider as PaperProvider, + MD2DarkTheme, + MD2LightTheme, } from 'react-native-paper'; import merge from 'deepmerge'; -const CombinedDefaultTheme = merge(PaperDefaultTheme, NavigationDefaultTheme); -const CombinedDarkTheme = merge(PaperDarkTheme, NavigationDarkTheme); +const CombinedDefaultTheme = merge(MD2DarkTheme, NavigationDefaultTheme); +const CombinedDarkTheme = merge(MD2LightTheme, NavigationDarkTheme); ``` -Alternatively, we could merge those themes using vanilla JavaScript +### Material Design 3 + +```js +import { + NavigationContainer, + DarkTheme as NavigationDarkTheme, + DefaultTheme as NavigationDefaultTheme, +} from '@react-navigation/native'; +import { + MD3DarkTheme, + MD3LightTheme, +} from 'react-native-paper'; +import merge from 'deepmerge'; + +const { LightTheme, DarkTheme } = adaptNavigationTheme({ + lightTheme: NavigationDefaultTheme, + darkTheme: NavigationDarkTheme, +}); + +const CombinedDefaultTheme = merge(MD2DarkTheme, LightTheme); +const CombinedDarkTheme = merge(MD2LightTheme, DarkTheme); +``` + +Alternatively, we could merge those themes using vanilla JavaScript: + +### Material Design 2 ```js const CombinedDefaultTheme = { - ...PaperDefaultTheme, + ...MD2LightTheme, ...NavigationDefaultTheme, colors: { - ...PaperDefaultTheme.colors, + ...MD2LightTheme.colors, ...NavigationDefaultTheme.colors, }, }; const CombinedDarkTheme = { - ...PaperDarkTheme, + ...MD2DarkTheme, ...NavigationDarkTheme, colors: { - ...PaperDarkTheme.colors, + ...MD2DarkTheme.colors, ...NavigationDarkTheme.colors, }, }; ``` +### Material Design 3 + +```js +const { LightTheme, DarkTheme } = adaptNavigationTheme({ + lightTheme: NavigationDefaultTheme, + darkTheme: NavigationDarkTheme, +}); + +const CombinedDefaultTheme = { + ...MD3LightTheme, + ...LightTheme, + colors: { + ...MD3LightTheme.colors, + ...LightTheme.colors, + }, +}; +const CombinedDarkTheme = { + ...MD3DarkTheme, + ...DarkTheme, + colors: { + ...MD3DarkTheme.colors, + ...DarkTheme.colors, + }, +}; +``` + ## Passing theme with Providers After combining the themes, we will be able to control theming in both libraries from a single source, which will come in handy later. @@ -128,9 +223,6 @@ After combining the themes, we will be able to control theming in both libraries Next, we need to pass merged themes into the Providers. For this part, we use the dark one - `CombinedDarkTheme`. ```js -const CombinedDefaultTheme = merge(PaperDefaultTheme, NavigationDefaultTheme); -const CombinedDarkTheme = merge(PaperDarkTheme, NavigationDarkTheme); - const Stack = createStackNavigator(); export default function App() { @@ -184,9 +276,6 @@ import { PreferencesContext } from './PreferencesContext'; const Stack = createStackNavigator(); -const CombinedDefaultTheme = merge(PaperDefaultTheme, NavigationDefaultTheme); -const CombinedDarkTheme = merge(PaperDarkTheme, NavigationDarkTheme); - export default function App() { const [isThemeDark, setIsThemeDark] = React.useState(false); @@ -242,7 +331,6 @@ const Header = ({ scene }) => { toggleTheme()}>