Appearance Module built on top of wix/react-native-navigation
npm install @busfor/react-native-navigation-appearance!npm




---
Make sure that your are using supported versions of react-native-navigation and react-native:
| 1.x |
| ------------------------------------------------------ |
| react-native-navigation >= 6.4.0; react-native: >=0.62 |
#### 1 Install dependencies
Make sure that you have installed @react-native-community/async-storage dependency or install it using:
$ yarn add @react-native-community/async-storage
Install this module using:
$ yarn add @busfor/react-native-navigation-appearance
#### 2 Update MainActivity.java
This file is located in android/app/src/main/java/com/.
``diff
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import com.busfor.rnnappearance.RNNAppearanceModuleKt;
public class MainActivity extends NavigationActivity {
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ RNNAppearanceModuleKt.setThemeResId(R.style.AppTheme);
+ }
}
`
#### 3 Configure android styles.xml
This file is located in android/app/src/main/res/values/styles.xml.
`diff
+
+
-
`
#### 4 Create android night styles.xml
This file should be located in android/app/src/main/res/values-night/styles.xml.
`xml
`
Make sure you don't have UIUserInterfaceStyle in Info.plist
1. Create a theme with dark and light appearances using createTheme function:
`javascript
import { createTheme } from '@busfor/react-native-navigation-appearance'
export const theme = createTheme({
dark: {
backgroundColor: '#121212',
textColor: '#fff',
primaryColor: 'blue',
},
light: {
backgroundColor: '#fff',
textColor: '#121212',
primaryColor: 'red',
},
})
`
2. Create default options using createDefaultOptions function:
`javascript
import { createDefaultOptions, Appearance } from '@busfor/react-native-navigation-appearance'
import { theme } from './theme'
export const defaultOptions = createDefaultOptions(({ appearance }) => ({
statusBar: {
style: appearance === Appearance.dark ? 'light' : 'dark',
backgroundColor: theme[appearance].backgroundColor,
},
navigationBar: {
backgroundColor: theme[appearance].backgroundColor,
},
topBar: {
background: {
color: theme[appearance].backgroundColor,
},
title: {
color: theme[appearance].textColor,
},
},
}))
`
3. Add ThemeProvider to register and init module with defaultOptions that we have created:
NOTE: Make sure that you are running initAppearanceModule inside Navigation.events().registerAppLaunchedListener callback and before Navigation.setRoot function!
`javascript
import { ThemeProvider, initAppearanceModule } from '@busfor/react-native-navigation-appearance'
Navigation.registerComponent(
'AppScreen',
() => (props) => (
),
() => AppScreen
)
Navigation.events().registerAppLaunchedListener(async () => {
await initAppearanceModule(defaultOptions)
Navigation.setRoot({ ... })
})
`
4. Create screen options using createOptions and defaultOptions functions:
This file should be located in /AppScreen/options.js
`javascript
import { createOptions } from '@busfor/react-native-navigation-appearance'
import { defaultOptions } from '../defaultOptions'
export default createOptions((props) =>
defaultOptions(props, {
// props contains the current appearance and passed props to the screen
topBar: {
title: {
text: props.appearance,
},
},
})
)
`
4. Create styles using createStyles function:
This file should be located in /AppScreen/styles.js
`javascript
import { createStyles } from '@busfor/react-native-navigation-appearance'
import { theme } from '../theme'
export default createStyles(({ appearance }) => ({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme[appearance].backgroundColor,
},
text: {
color: theme[appearance].textColor,
paddingVertical: 8,
textAlign: 'center',
},
}))
`
6. Use useThemedOptions, initialOptions to define screen options and use useStyles hook to provide styles:
This file should be located in /AppScreen/index.js
`javascript
import React from 'react'
import { Text, SafeAreaView } from 'react-native'
import { useStyles, initialOptions, useThemedOptions } from '@busfor/react-native-navigation-appearance'
import stylesCreator from './styles'
import options from './options'
const AppScreen = ({ componentId }) => {
useThemedOptions({}, options, componentId)
const styles = useStyles(stylesCreator)
return (
)
}
AppScreen.options = initialOptions(options)
export default AppScreen
`
Also you can open the example project to see how it works in the real case.
You can set appearance manually using useThemeControls hook:
`javascript
import { useThemeControls, AppearanceMode } from '@busfor/react-native-navigation-appearance'
const App = () => {
const { currentApearanceMode, setAppearanceMode } = useThemeControls()
return (
<>
You can get current appearance using useAppearance hook:
`javascript
import { useAppearance, Appearance } from '@busfor/react-native-navigation-appearance'
const App = () => {
const appearance = useAppearance()
return
}
`
You can get any value for current appearance using useThemedValue hook:
`javascript
import { useThemedValue } from '@busfor/react-native-navigation-appearance'
const lightLogoSource = require('./lightLogo.png')
const darkLogoSource = require('./darkLogo.png')
const App = () => {
const logoSource = useThemedValue({ light: lightLogoSource, dark: darkLogoSource })
return
}
`
With this function, you can select specific unique styles and options per appearance (like Platform.select)
`javascript
import { createOptions, appearanceSelect } from '@busfor/react-native-navigation-appearance'
import { defaultOptions } from '../defaultOptions'
export default createOptions((props) =>
defaultOptions(props, {
topBar: {
title: {
text: appearanceSelect(props.appearance, {
light: 'This is text for the light appearance',
dark: 'This is text for the dark appearance',
}),
},
},
})
)
`
1. Update your Jest setup file:
`javascript
import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock'
import '@busfor/react-native-navigation-appearance/jest/rnn-appearance-mock'
jest.mock('@react-native-community/async-storage', () => mockAsyncStorage)
jest.useFakeTimers()
`
2. Use setDarkModeMock in your test cases:
`javascript
import { setDarkModeMock } from '@busfor/react-native-navigation-appearance'
describe('Theming', () => {
afterEach(() => {
setDarkModeMock(false)
})
it(dark theme, () => {light theme
setDarkModeMock(true)
...
})s
it(, () => {``
...
})
})