UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

259 lines (179 loc) 6.84 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** - `createTheming(defaultTheme)` - factory returns: - `ThemeProvider` - component - `withTheme` - Higher Order Component - `useTheme` - React Hook ## Examples - built-in 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 ### Installation ```sh npm install --save @callstack/react-theme-provider ``` or using yarn ```sh yarn add @callstack/react-theme-provider ``` ### Usage Import `createTheming` from the library to create a theming object. ```js 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. ```js <ThemeProvider> <App /> </ThemeProvider> ``` You can access the theme data in your components by wrapping it in `withTheme` HOC: ```js 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](https://reactjs.org/docs/hooks-intro.html) based API: ```js function App() { const theme = useTheme(); return <div style={{ color: theme.primaryColor }}>Hello</div>; } ``` ### 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. ### 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'; ``` ### Helpers #### `ThemeProvider` **type:** ```js 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. ##### Props -`theme` - your theme object #### `withTheme` **type:** ```js type WithThemeType<Theme> = React.ComponentType<{ theme: Theme }> ``` Higher Order Component which takes your component as an argument and injects `theme` prop into it. ## 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>; } ``` #### `useTheme` **type:** ```js type UseTheme = (overrides?: PartialTheme) => Theme; ``` Hook which takes theme overrides and returns a theme object. Example: ```js function App(props) { const theme = useTheme(props.theme); return <div style={{ color: theme.primaryColor }}>Hello</div>; } ``` ## 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/