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 | `@callstack/react-theme-provider` is a set of utilities that help you create your own theming system in few easy steps.
|
13 | You can use it to customize colors, fonts, etc.
|
14 |
|
15 | ## Features
|
16 | - works in **React** and **React Native**
|
17 | - `ThemeProvider` - component
|
18 | - `withTheme` - Higher Order Component
|
19 | - `createTheming(defaultTheme)` - factory returns `ThemeProvider` component and `withTheme` HOC with default theme injected.
|
20 |
|
21 | ## Examples
|
22 | - buildin example for web react - ['/examples/web'](/examples/web)
|
23 | - [![Edit v6o562k6l7](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/v6o562k6l7)
|
24 |
|
25 | ## Getting started
|
26 | ### Instalation
|
27 | ```
|
28 | npm install --save @callstack/react-theme-provider
|
29 | ```
|
30 | or using yarn
|
31 | ```
|
32 | yarn add @callstack/react-theme-provider
|
33 | ```
|
34 |
|
35 | ### Usage
|
36 | To use, simply wrap your code into `ThemeProvider` component and pass your theme as a `theme` prop.
|
37 |
|
38 | ```js
|
39 | <ThemeProvider theme={{ primaryColor: 'red', background: 'gray'}}>
|
40 | <App />
|
41 | </ThemeProvider>
|
42 | ```
|
43 |
|
44 | You could access theme data inside every component by wraping it into `withTheme` HOC. Just like this:
|
45 |
|
46 | ```js
|
47 | class App extends React.Component {
|
48 | render() {
|
49 | return (
|
50 | <div style={{ color: props.theme.primaryColor }}>
|
51 | Hello
|
52 | </div>
|
53 | );
|
54 | }
|
55 | }
|
56 |
|
57 | export default withTheme(App);
|
58 | ```
|
59 |
|
60 | ## `ThemeProvider`
|
61 | **type:**
|
62 | ```js
|
63 | type ThemeProviderType<T> = React.ComponentType<{
|
64 | children?: any,
|
65 | theme: T,
|
66 | }>
|
67 | ```
|
68 |
|
69 | Component you have to use to provide the theme to any component wrapped in `withTheme` HOC.
|
70 |
|
71 | ### props
|
72 | -`theme` - your theme object
|
73 |
|
74 | ## `withTheme`
|
75 | **type:**
|
76 | ```js
|
77 | type WithThemeType<T, S> = <C: React.ComponentType<*>>(
|
78 | Comp: C
|
79 | ) => C &
|
80 | React.ComponentType<
|
81 | $Diff<React.ElementConfig<C>, { theme: T }> & { theme?: S }
|
82 | >;
|
83 | ```
|
84 |
|
85 | Classic Higher Order Component which takes your component as an argument and injects `theme` prop into it.
|
86 |
|
87 | ### Example of usage
|
88 | ```js
|
89 | const App = ({ theme }) => (
|
90 | <div style={{ color: theme.primaryColor }}>
|
91 | Hello
|
92 | </div>
|
93 | );
|
94 |
|
95 | export withTheme(App);
|
96 | ```
|
97 |
|
98 | ### Injected props
|
99 | It will inject the following props to the component:
|
100 | - `theme` - our theme object.
|
101 | - `getWrappedInstance` - exposed by some HOCs like react-redux's `connect`.
|
102 | Use it to get the ref of the underlying element.
|
103 |
|
104 | ### Injecting theme by a direct prop
|
105 | You can also override `theme` provided by `ThemeProvider` by setting `theme` prop on the component wrapped in `withTheme` HOC.
|
106 |
|
107 | Just like this:
|
108 | ```js
|
109 | const Button = withTheme(({ theme }) => (
|
110 | <div style={{ color: theme.primaryColor }}>
|
111 | Click me
|
112 | </div>
|
113 | ));
|
114 |
|
115 | const App = () => (
|
116 | <ThemeProvider theme={{ primaryColor: 'red' }}>
|
117 | <Button theme= {{ primaryColor: 'green' }}/>
|
118 | </ThemeProvider>
|
119 | )
|
120 | ```
|
121 | In this example Button will have green text.
|
122 |
|
123 | ## `createTheming`
|
124 | **type:**
|
125 | ```js
|
126 | <T, S>(defaultTheme: T) => {
|
127 | ThemeProvider: ThemeProviderType<T>,
|
128 | withTheme: WithThemeType<T, S>,
|
129 | }
|
130 | ```
|
131 |
|
132 | This is more advanced replacement to classic importing `ThemeProvider` and `withTheme` directly from the library.
|
133 | Thanks to it you can create your own ThemeProvider with any default theme.
|
134 |
|
135 | Returns instance of `ThemeProvider` component and `withTheme` HOC.
|
136 | You can use this factory to create a singleton with your instances of `ThemeProvider` and `withTheme`.
|
137 |
|
138 | >**Note:** `ThemeProvider` and `withTheme` generated by `createTheming` always will use different context so make sure you are using matching `withTheme`!
|
139 | If you acidentially import `withTheme` from `@callstack/react-theme-provider` instead of your theming instance it won't work.
|
140 |
|
141 | ### Arguments
|
142 | - `defaultTheme` - default theme object
|
143 |
|
144 | ### Benefits
|
145 | - Possibility to define `flow` types for your theme
|
146 | - Possibility to pass default theme
|
147 | - You can use multiple `ThemeProvider`s in your app without any conflicts.
|
148 |
|
149 | ### Example of usage
|
150 | ```js
|
151 | // theming.js
|
152 | import { createTheming } from '@callstack/react-theme-provider';
|
153 | const { ThemeProvider, withTheme } = createTheming({
|
154 | primaryColor: 'red',
|
155 | secondaryColor: 'green',
|
156 | });
|
157 | export { ThemeProvider, withTheme };
|
158 |
|
159 | //App.js
|
160 | import { ThemeProvider, withTheme } from './theming';
|
161 | ```
|
162 |
|
163 | ## Applying a custom theme to a component
|
164 | 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.
|
165 |
|
166 | ```js
|
167 | import * as React from 'react';
|
168 | import MyButton from './MyButton';
|
169 |
|
170 | export default function ButtonExample() {
|
171 | return (
|
172 | <MyButton theme={{ roundness: 3 }}>
|
173 | Press me
|
174 | </MyButton>
|
175 | );
|
176 | }
|
177 | ```
|
178 |
|
179 | ## Gotchas
|
180 | The `ThemeProvider` exposes the theme to the components via [React's context API](https://reactjs.org/docs/context.html),
|
181 | which means that the component must be in the same tree as the `ThemeProvider`. Some React Native components will render a
|
182 | different tree such as a `Modal`, in which case the components inside the `Modal` won't be able to access the theme. The work
|
183 | 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
|
184 | exported `ThemeProvider` component.
|
185 |
|
186 |
|
187 | [build-badge]: https://img.shields.io/circleci/project/github/callstack/react-theme-provider/master.svg?style=flat-square
|
188 | [build]: https://circleci.com/gh/callstack/react-theme-provider
|
189 | [version-badge]: https://img.shields.io/npm/v/@callstack/react-theme-provider.svg?style=flat-square
|
190 | [package]: https://www.npmjs.com/package/@callstack/react-theme-provider
|
191 | [license-badge]: https://img.shields.io/npm/l/react-theme-provider.svg?style=flat-square
|
192 | [license]: https://opensource.org/licenses/MIT
|
193 | [chat-badge]: https://img.shields.io/badge/chat-slack-brightgreen.svg?style=flat-square&colorB=E01563
|
194 | [chat]: https://slack.callstack.com/ |
\ | No newline at end of file |