@callstack/react-theme-provider
is a set of utilities that help you create your own theming system in few easy steps.
You can use it to customize colors, fonts, etc.
- Works in React and React Native
createTheming(defaultTheme)
- factory returns:ThemeProvider
- componentwithTheme
- Higher Order ComponentuseTheme
- React Hook
- built-in example for web react - '/examples/web'
npm install --save @callstack/react-theme-provider
or using yarn
yarn add @callstack/react-theme-provider
Import createTheming
from the library to create a theming object.
import { createTheming } from '@callstack/react-theme-provider';
const { ThemeProvider, withTheme, useTheme } = createTheming(defaultTheme);
Then wrap your code in ThemeProvider
component to make it available to all components.
<ThemeProvider>
<App />
</ThemeProvider>
You can access the theme data in your components by wrapping it in withTheme
HOC:
class App extends React.Component {
render() {
return <div style={{ color: props.theme.primaryColor }}>Hello</div>;
}
}
export default withTheme(App);
You can also use the hooks based API:
function App() {
const theme = useTheme();
return <div style={{ color: theme.primaryColor }}>Hello</div>;
}
const App = ({ theme }) => (
<div style={{ color: theme.primaryColor }}>
Hello
</div>
);
export withTheme(App);
It will inject the following props to the component:
theme
- our theme object.getWrappedInstance
- exposed by some HOCs like react-redux'sconnect
. Use it to get the ref of the underlying element.
You can also override theme
provided by ThemeProvider
by setting theme
prop on the component wrapped in withTheme
HOC.
Just like this:
const Button = withTheme(({ theme }) => (
<div style={{ color: theme.primaryColor }}>Click me</div>
));
const App = () => (
<ThemeProvider theme={{ primaryColor: 'red' }}>
<Button theme={{ primaryColor: 'green' }} />
</ThemeProvider>
);
In this example Button will have green text.
type:
<T, S>(defaultTheme: T) => {
ThemeProvider: ThemeProviderType<T>,
withTheme: WithThemeType<T, S>,
}
This is more advanced replacement to classic importing ThemeProvider
and withTheme
directly from the library.
Thanks to it you can create your own ThemeProvider with any default theme.
Returns instance of ThemeProvider
component and withTheme
HOC.
You can use this factory to create a singleton with your instances of ThemeProvider
and withTheme
.
Note:
ThemeProvider
andwithTheme
generated bycreateTheming
always will use different context so make sure you are using matchingwithTheme
! If you acidentially importwithTheme
from@callstack/react-theme-provider
instead of your theming instance it won't work.
defaultTheme
- default theme object
- Possibility to define
flow
types for your theme - Possibility to pass default theme
- You can use multiple
ThemeProvider
s in your app without any conflicts.
// theming.js
import { createTheming } from '@callstack/react-theme-provider';
const { ThemeProvider, withTheme } = createTheming({
primaryColor: 'red',
secondaryColor: 'green',
});
export { ThemeProvider, withTheme };
//App.js
import { ThemeProvider, withTheme } from './theming';
type:
type ThemeProviderType<Theme> = React.ComponentType<{
children: React.Node,
theme?: Theme,
}>;
Component you have to use to provide the theme to any component wrapped in withTheme
HOC.
-theme
- your theme object
type:
type WithThemeType<Theme> = React.ComponentType<{ theme: Theme }>
Higher Order Component which takes your component as an argument and injects theme
prop into it.
If you want to change the theme for a certain component, you can directly pass the theme prop to the component. The theme passed as the prop is merged with the theme from the Provider.
import * as React from 'react';
import MyButton from './MyButton';
export default function ButtonExample() {
return <MyButton theme={{ roundness: 3 }}>Press me</MyButton>;
}
type:
type UseTheme = (overrides?: PartialTheme) => Theme;
Hook which takes theme overrides and returns a theme object.
Example:
function App(props) {
const theme = useTheme(props.theme);
return <div style={{ color: theme.primaryColor }}>Hello</div>;
}
If you want to change the theme for a certain component, you can directly pass the theme prop to the component. The theme passed as the prop is merged with the theme from the Provider.
import * as React from 'react';
import MyButton from './MyButton';
export default function ButtonExample() {
return <MyButton theme={{ roundness: 3 }}>Press me</MyButton>;
}
The ThemeProvider
exposes the theme to the components via React's context API,
which means that the component must be in the same tree as the ThemeProvider
. Some React Native components will render a
different tree such as a Modal
, in which case the components inside the Modal
won't be able to access the theme. The work
around is to get the theme using the withTheme
HOC and pass it down to the components as props, or expose it again with the
exported ThemeProvider
component.