Skip to content

Theming

Theming
All platforms
2.0.0

Theming in Unistyles differs from other libraries as it doesn’t impose any specific syntax.

Any JavaScript object can be a Unistyles theme.

There is also no limit to the number of themes. You can even register dozens of them, for example, if your app sells some premium ones.

Theming is optional. If you dont’t register themes with UnistylesRegistry the library will use an empty object by default.

Create a theme

You can organize your themes however you want:

const myTheme = {
// any keys
colors: {
// your colors
},
components: {
// any number of nesting
button: {
deepKey: {}
}
},
utils: {
// you can even use functions here
hexToRGBA: () => {}
},
// or compute your themes with functions and spread operators
...premiumFeatures,
...getMyColors()
}

If you use TypeScript you need to override the library’s type:

type AppThemes = {
name: typeof myTheme
}
declare module 'react-native-unistyles' {
export interface UnistylesThemes extends AppThemes {}
}

Finally, to register the theme, you need to call UnistylesRegistry:

import { UnistylesRegistry } from 'react-native-unistyles'
import { myTheme } from './themes'
UnistylesRegistry
.addThemes({
name: myTheme,
// you can add more themes here
})

Where name is the unique name of your theme.

Select theme

If you’ve registered more than one theme, Unistyles won’t know which one is the initial one. At this point, you have 3 options:

  • If you know the initial theme upfront, select it with addConfig from UnistylesRegistry
UnistylesRegistry
.addThemes({
light: myTheme,
premium: premiumTheme
})
.addConfig({
initialTheme: 'premium'
})
  • If you need to resolve the user-selected theme during runtime, call useInitialTheme before using your first useStyles hook:
import { useInitialTheme, useStyles } from 'react-native-unistyles'
const App = () => {
// can be read from any storage eg. stan-js/MMKV/SQL
const { userTheme } = useStore()
// pass theme name to useInitialTheme hook
useInitialTheme(userTheme)
// useInitialTheme must be called before the first useStyles hook
// it's so fast that you can even call it in the same component!
const { styles } = useStyles(stylesheet)
return (
// your app's JSX
)
}
  • Use adaptive themes, which are described below

Get the current theme

To get the current theme, you can either obtain it from the useStyles hook:

const { theme } = useStyles()

or access it in the createStyleSheet function:

const stylesheet = createStyleSheet(theme => ({
...
}))

Get the current theme name

To get the current theme name, import UnistylesRuntime:

import { UnistylesRuntime } from 'react-native-unistyles'
// access the current theme name in your component
export const UserTheme = () => (
<Text>
Selected theme is {UnistylesRuntime.themeName}
</Text>
)

Adaptive themes

Adaptive themes allow Unistyles to automatically manage the selection of your themes based on device color scheme settings. To enable this, you need to meet two conditions:

  • register two themes with reserved names light and dark:
UnistylesRegistry
.addThemes({
light: lightTheme,
dark: darkTheme,
// you may have more themes
})
  • Explicitly enable adaptiveThemes:
UnistylesRegistry
.addThemes({
light: lightTheme,
dark: darkTheme,
// you may have more themes
})
.addConfig({
adaptiveThemes: true
})

In order to support adaptiveThemes with SSR, please follow this guide.

Toggle adaptive themes during runtime

To toggle adaptive theme support at any point, use UnistylesRuntime:

import { UnistylesRuntime } from 'react-native-unistyles'
// toggle support for adaptive themes at any point
export const ToggleAdaptiveThemes = () => (
<Button
title="Disable adaptive themes"
onPress={() => UnistylesRuntime.setAdaptiveThemes(false)}
/>
)

Check if adaptive themes are enabled

To check if adaptive themes are enabled, again use UnistylesRuntime:

import { UnistylesRuntime } from 'react-native-unistyles'
// check if you've enabled adaptive themes
export const AdaptiveThemes = () => (
<Text>
Adaptive themes are {UnistylesRuntime.hasAdaptiveThemes ? 'enabled' : 'disabled'}
</Text>
)

Get device color scheme

Check your device color preference with UnistylesRuntime:

import { UnistylesRuntime } from 'react-native-unistyles'
// check the current device scheme preference
export const UserTheme = () => (
<Text>
My device is using the {UnistylesRuntime.colorScheme} scheme.
</Text>
)

Available options are: dark, light or unspecified for devices that don’t support color schemes.

If your app’s theme is not changing based on device settings, please refer to the FAQ

Change theme

With Unistyles 2.0, we no longer use a React Context. However, this doesn’t mean you can’t change the theme. In fact, it’s even easier as you don’t need to re-render the entire app. To change the theme at any time, simply call setTheme function:

import { UnistylesRuntime } from 'react-native-unistyles'
// change the theme in any component
export const ChangeTheme = () => (
<Button
title="Change theme"
onPress={() => UnistylesRuntime.setTheme('dark')}
/>
)

Update theme during runtime

All platforms
2.2.0

Unistyles allows you to update your theme during runtime. This is useful if you want to show the user interface with default colors and later alter theme based on user preferences.

If you update the currently selected theme, it will be automatically applied, and Unistyles will notify all stylesheets about the change. Otherwise, theme will be updated silently.

To update the theme during runtime, call updateTheme function, and return new theme object:

import { UnistylesRuntime } from 'react-native-unistyles'
// update the theme at any time
export const UpdateTheme = ({ selectedColors }) => (
<Button
title="Update theme"
onPress={() => UnistylesRuntime.updateTheme('dark', currentTheme => ({
...currentTheme,
colors: {
...currentTheme.colors,
...selectedColors
}
}))}
/>
)

Update statusBar color during runtime

Android
2.6.0 - 2.8.0

Sometimes your app needs to dynamically change the status bar color, for example, when entering image preview or on some onboarding screens. You can easily update the color with UnistylesRuntime and for example the useEffect hook:

import React, { useEffect } from 'react'
import { UnistylesRuntime, useStyles } from 'react-native-unistyles'
export const OnboardingScreen = () => {
const { theme } = useStyles()
useEffect(() => {
UnistylesRuntime.statusBar.setColor(theme.colors.primary)
// or with alpha channel
UnistylesRuntime.statusBar.setColor(theme.colors.primary, 0.5)
return () => {
// set default color
UnistylesRuntime.statusBar.setColor(undefined)
}
}, [])
// your onboarding JSX
return ()
}

Update navigationBar color during runtime

Android
2.6.0 - 2.8.0

Just as with the statusBar, you can do the same with the navigationBar and set a specified color.

import React, { useEffect } from 'react'
import { UnistylesRuntime, useStyles } from 'react-native-unistyles'
export const ImagePreview = ({ imageUri }) => {
const { theme } = useStyles()
useEffect(() => {
UnistylesRuntime.navigationBar.setColor(theme.colors.black)
// or with 8-digit hex value eg. #50000000
UnistylesRuntime.navigationBar.setColor(theme.colors.halfBlack)
return () => {
// set default color
UnistylesRuntime.navigationBar.setColor(undefined)
}
}, [])
// your image preview JSX
return ()
}

Update rootView background color during runtime

iOS
Android
Web
2.8.0

You can also change dynamically the root view background color with UnistylesRuntime:

import { UnistylesRuntime } from 'react-native-unistyles'
// update the theme at any time
export const UpdateTheme = ({ selectedColors }) => (
<Button
title="Update theme"
onPress={() => UnistylesRuntime.setRootViewBackgroundColor(theme.colors.primary)}
/>
)

Changing rootView background color is useful when your app supports different orientations and you want to match the background color with your theme while transitioning.

System bars and rootView colors

Unistyles supports all 6- and 8-character hex colors with a # prefix, as well as some built-in colors:

translucent red, blue, green, black, white, gray, cyan, magenta, yellow, light gray, dark gray, grey, light grey, dark grey, aqua, fuchsia, lime, maroon, navy, olive, purple, silver, and teal.

2.8.0

Since version 2.8.0, Unistyles supports optional alpha value that can easily convert hex values to transparency.

UnistylesRuntime.statusBar.setColor(theme.colors.black) // #000000
UnistylesRuntime.statusBar.setColor(theme.colors.halfBlack) // #80000000
UnistylesRuntime.navigationBar.setColor(theme.colors.halfBlack, 0.5) // #000000 , 0.5 opacity
UnistylesRuntime.navigationBar.setColor('red', 0.5) // opacity will be ignored
UnistylesRuntime.statusBar.setColor(theme.colors.halfBlack, 0.2) // opacity will be ignored

In case of any issue in parsing Unistyles will silently fail without a crash.