UNPKG

6.83 kBMarkdownView Raw
1<p align="center">
2 <img alt="react-theme-provider" src="./assets/theme-provider-logo.png" width="496">
3</p>
4
5---
6
7[![Build Status][build-badge]][build]
8[![Version][version-badge]][package]
9[![MIT License][license-badge]][license]
10
11## About
12
13`@callstack/react-theme-provider` is a set of utilities that help you create your own theming system in few easy steps.
14You can use it to customize colors, fonts, etc.
15
16## Features
17
18- Works in **React** and **React Native**
19- `createTheming(defaultTheme)` - factory returns:
20 - `ThemeProvider` - component
21 - `withTheme` - Higher Order Component
22 - `useTheme` - React Hook
23
24## Examples
25
26- built-in example for web react - ['/examples/web'](/examples/web)
27- [![Edit v6o562k6l7](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/v6o562k6l7)
28
29## Getting started
30
31### Installation
32
33```sh
34npm install --save @callstack/react-theme-provider
35```
36
37or using yarn
38
39```sh
40yarn add @callstack/react-theme-provider
41```
42
43### Usage
44
45Import `createTheming` from the library to create a theming object.
46
47```js
48import { createTheming } from '@callstack/theme-provider';
49
50const { ThemeProvider, withTheme, useTheme } = createTheming(defaultTheme);
51```
52
53Then wrap your code in `ThemeProvider` component to make it available to all components.
54
55```js
56<ThemeProvider>
57 <App />
58</ThemeProvider>
59```
60
61You can access the theme data in your components by wrapping it in `withTheme` HOC:
62
63```js
64class App extends React.Component {
65 render() {
66 return <div style={{ color: props.theme.primaryColor }}>Hello</div>;
67 }
68}
69
70export default withTheme(App);
71```
72
73You can also use the [hooks](https://reactjs.org/docs/hooks-intro.html) based API:
74
75```js
76function App() {
77 const theme = useTheme();
78
79 return <div style={{ color: theme.primaryColor }}>Hello</div>;
80}
81```
82
83### Usage
84
85```js
86const App = ({ theme }) => (
87 <div style={{ color: theme.primaryColor }}>
88 Hello
89 </div>
90);
91
92export withTheme(App);
93```
94
95### Injected props
96
97It will inject the following props to the component:
98
99- `theme` - our theme object.
100- `getWrappedInstance` - exposed by some HOCs like react-redux's `connect`.
101 Use it to get the ref of the underlying element.
102
103### Injecting theme by a direct prop
104
105You can also override `theme` provided by `ThemeProvider` by setting `theme` prop on the component wrapped in `withTheme` HOC.
106
107Just like this:
108
109```js
110const Button = withTheme(({ theme }) => (
111 <div style={{ color: theme.primaryColor }}>Click me</div>
112));
113
114const App = () => (
115 <ThemeProvider theme={{ primaryColor: 'red' }}>
116 <Button theme={{ primaryColor: 'green' }} />
117 </ThemeProvider>
118);
119```
120
121In this example Button will have green text.
122
123## `createTheming`
124
125**type:**
126
127```js
128<T, S>(defaultTheme: T) => {
129 ThemeProvider: ThemeProviderType<T>,
130 withTheme: WithThemeType<T, S>,
131}
132```
133
134This is more advanced replacement to classic importing `ThemeProvider` and `withTheme` directly from the library.
135Thanks to it you can create your own ThemeProvider with any default theme.
136
137Returns instance of `ThemeProvider` component and `withTheme` HOC.
138You can use this factory to create a singleton with your instances of `ThemeProvider` and `withTheme`.
139
140> **Note:** `ThemeProvider` and `withTheme` generated by `createTheming` always will use different context so make sure you are using matching `withTheme`!
141> If you acidentially import `withTheme` from `@callstack/react-theme-provider` instead of your theming instance it won't work.
142
143### Arguments
144
145- `defaultTheme` - default theme object
146
147### Benefits
148
149- Possibility to define `flow` types for your theme
150- Possibility to pass default theme
151- You can use multiple `ThemeProvider`s in your app without any conflicts.
152
153### Usage
154
155```js
156// theming.js
157import { createTheming } from '@callstack/react-theme-provider';
158const { ThemeProvider, withTheme } = createTheming({
159 primaryColor: 'red',
160 secondaryColor: 'green',
161});
162export { ThemeProvider, withTheme };
163
164//App.js
165import { ThemeProvider, withTheme } from './theming';
166```
167
168### Helpers
169
170#### `ThemeProvider`
171
172**type:**
173
174```js
175type ThemeProviderType<Theme> = React.ComponentType<{
176 children: React.Node,
177 theme?: Theme,
178}>;
179```
180
181Component you have to use to provide the theme to any component wrapped in `withTheme` HOC.
182
183##### Props
184
185-`theme` - your theme object
186
187#### `withTheme`
188
189**type:**
190
191```js
192type WithThemeType<Theme> = React.ComponentType<{ theme: Theme }>
193```
194
195Higher Order Component which takes your component as an argument and injects `theme` prop into it.
196
197## Applying a custom theme to a component
198
199If 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.
200
201```js
202import * as React from 'react';
203import MyButton from './MyButton';
204
205export default function ButtonExample() {
206 return <MyButton theme={{ roundness: 3 }}>Press me</MyButton>;
207}
208```
209
210#### `useTheme`
211
212**type:**
213
214```js
215type UseTheme = (overrides?: PartialTheme) => Theme;
216```
217
218Hook which takes theme overrides and returns a theme object.
219
220Example:
221
222```js
223function App(props) {
224 const theme = useTheme(props.theme);
225
226 return <div style={{ color: theme.primaryColor }}>Hello</div>;
227}
228```
229
230## Applying a custom theme to a component
231
232If 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.
233
234```js
235import * as React from 'react';
236import MyButton from './MyButton';
237
238export default function ButtonExample() {
239 return <MyButton theme={{ roundness: 3 }}>Press me</MyButton>;
240}
241```
242
243## Gotchas
244
245The `ThemeProvider` exposes the theme to the components via [React's context API](https://reactjs.org/docs/context.html),
246which means that the component must be in the same tree as the `ThemeProvider`. Some React Native components will render a
247different tree such as a `Modal`, in which case the components inside the `Modal` won't be able to access the theme. The work
248around is to get the theme using the `withTheme` HOC and pass it down to the components as props, or expose it again with the
249exported `ThemeProvider` component.
250
251[build-badge]: https://img.shields.io/circleci/project/github/callstack/react-theme-provider/master.svg?style=flat-square
252[build]: https://circleci.com/gh/callstack/react-theme-provider
253[version-badge]: https://img.shields.io/npm/v/@callstack/react-theme-provider.svg?style=flat-square
254[package]: https://www.npmjs.com/package/@callstack/react-theme-provider
255[license-badge]: https://img.shields.io/npm/l/react-theme-provider.svg?style=flat-square
256[license]: https://opensource.org/licenses/MIT
257[chat-badge]: https://img.shields.io/badge/chat-slack-brightgreen.svg?style=flat-square&colorB=E01563
258[chat]: https://slack.callstack.com/