UNPKG

@callstack/react-theme-provider

Version:

Theme provider for react and react-naitve applications

194 lines (158 loc) 5.96 kB
<p align="center"> <img alt="react-theme-provider" src="./assets/theme-provider-logo.png" width="496"> </p> --- [![Build Status][build-badge]][build] [![Version][version-badge]][package] [![MIT License][license-badge]][license] ## About `@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. ## Features - works in **React** and **React Native** - `ThemeProvider` - component - `withTheme` - Higher Order Component - `createTheming(defaultTheme)` - factory returns `ThemeProvider` component and `withTheme` HOC with default theme injected. ## Examples - buildin example for web react - ['/examples/web'](/examples/web) - [![Edit v6o562k6l7](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/v6o562k6l7) ## Getting started ### Instalation ``` npm install --save @callstack/react-theme-provider ``` or using yarn ``` yarn add @callstack/react-theme-provider ``` ### Usage To use, simply wrap your code into `ThemeProvider` component and pass your theme as a `theme` prop. ```js <ThemeProvider theme={{ primaryColor: 'red', background: 'gray'}}> <App /> </ThemeProvider> ``` You could access theme data inside every component by wraping it into `withTheme` HOC. Just like this: ```js class App extends React.Component { render() { return ( <div style={{ color: props.theme.primaryColor }}> Hello </div> ); } } export default withTheme(App); ``` ## `ThemeProvider` **type:** ```js type ThemeProviderType<T> = React.ComponentType<{ children?: any, theme: T, }> ``` Component you have to use to provide the theme to any component wrapped in `withTheme` HOC. ### props -`theme` - your theme object ## `withTheme` **type:** ```js type WithThemeType<T, S> = <C: React.ComponentType<*>>( Comp: C ) => C & React.ComponentType< $Diff<React.ElementConfig<C>, { theme: T }> & { theme?: S } >; ``` Classic Higher Order Component which takes your component as an argument and injects `theme` prop into it. ### Example of usage ```js const App = ({ theme }) => ( <div style={{ color: theme.primaryColor }}> Hello </div> ); export withTheme(App); ``` ### Injected props It will inject the following props to the component: - `theme` - our theme object. - `getWrappedInstance` - exposed by some HOCs like react-redux's `connect`. Use it to get the ref of the underlying element. ### Injecting theme by a direct prop You can also override `theme` provided by `ThemeProvider` by setting `theme` prop on the component wrapped in `withTheme` HOC. Just like this: ```js 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. ## `createTheming` **type:** ```js <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` and `withTheme` generated by `createTheming` always will use different context so make sure you are using matching `withTheme`! If you acidentially import `withTheme` from `@callstack/react-theme-provider` instead of your theming instance it won't work. ### Arguments - `defaultTheme` - default theme object ### Benefits - 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. ### Example of usage ```js // 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'; ``` ## Applying a custom theme to a component 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. ```js import * as React from 'react'; import MyButton from './MyButton'; export default function ButtonExample() { return ( <MyButton theme={{ roundness: 3 }}> Press me </MyButton> ); } ``` ## Gotchas The `ThemeProvider` exposes the theme to the components via [React's context API](https://reactjs.org/docs/context.html), 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. [build-badge]: https://img.shields.io/circleci/project/github/callstack/react-theme-provider/master.svg?style=flat-square [build]: https://circleci.com/gh/callstack/react-theme-provider [version-badge]: https://img.shields.io/npm/v/@callstack/react-theme-provider.svg?style=flat-square [package]: https://www.npmjs.com/package/@callstack/react-theme-provider [license-badge]: https://img.shields.io/npm/l/react-theme-provider.svg?style=flat-square [license]: https://opensource.org/licenses/MIT [chat-badge]: https://img.shields.io/badge/chat-slack-brightgreen.svg?style=flat-square&colorB=E01563 [chat]: https://slack.callstack.com/