Skip to content

React Native Theme a abstraction over StyleSheet.

License

Notifications You must be signed in to change notification settings

MNUI/theme-provider

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Native Theme Provider

A theme abstraction over React Native StyleSheet. Thanks to @brankeye for great work this package forked from react-native-paint

Nested Theme Support

Usage

Step 1

Install react-native-theme-provider using yarn or npm.

yarn add @material-native-ui/theme-provider
npm install @material-native-ui/theme-provider

Step 2

Wrap your App with a theme provider.

import React from "react";
import { ThemeProvider } from "@material-native-ui/theme-provider";

const defaultTheme = {
    spacing: (spacing) => 8 * spacing,
}


const themes = {
  light: {
    ...defaultTheme,
    name: "light",
    // some light theme properties
    palette: {
        default: 'rgba(100, 100, 100, .5)',
        primary: '#40A3D0',
        secondary: '#F5FF62',
    }
  },
  dark: {
    ...defaultTheme,
    name: "dark",
    // some dark theme properties
    palette: {
        default: 'rgba(200, 200, 200, .5)',
        primary: '#ffbb00',
        secondary: '#ff6501',
    }
  }
};

class App extends React.Component {
  state = {
    currentTheme: themes.light
  };

  changeTheme = () => {
    const { name } = this.state.currentTheme;
    const nextTheme = name === "light" ? themes.dark : themes.light;
    this.setState({
      currentTheme: nextTheme
    });
  };

  render() {
    const { currentTheme } = this.state;
    return (
      <ThemeProvider theme={currentTheme}>
        <App changeTheme={this.changeTheme} />
      </ThemeProvider>
    );
  }
}

Step 3

import React, { Component } from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import StyleSheet, { withStyles } from '@material-native-ui/theme-provider'

class App extends Component {
  render() {
    const { styles, changeTheme } = this.props
    return (
      <View style={styles.container}>
        <Text style={styles.title}>Awesome Theme Provider</Text>
        <View style={styles.actions}>
          <TouchableOpacity style={styles.button} onPress={changeTheme('dark')}>
            <Text>dark</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.button} onPress={changeTheme('light')}>
            <Text>light</Text>
          </TouchableOpacity>
        </View>
      </View>
    )
  }
}

const style = StyleSheet.create(
  (theme) => ({
    container: {
      flexGrow: 1,
      paddingTop: theme.spacing(4),
      paddingBottom: theme.spacing(2),
      paddingLeft: theme.spacing(2),
      paddingRight: theme.spacing(2),
    },
    title: {
      marginBottom: theme.spacing(2),
    },
    button: {
      borderRadius: 5,
      justifyContent: 'center',
      flexDirection: 'row',
      backgroundColor: theme.palette.default,
    },
    actions: {
      flexDirection: 'row',
    },
  })
)
export default withStyles(style)(App)

Nested Theme

        <ThemeProvider theme={themes.green}>
            <Button color={'primary'} text="Submit" />
            <ThemeProvider theme={themes.blue}>
              <Button color={'primary'} text="Submit" />
            </ThemeProvider>
        <ThemeProvider theme={themes.light}>

useStyle hook

import React, { Component } from 'react'
import StyleSheet, { useStyle } from '@material-native-ui/theme-provider'

const style = StyleSheet.create(
  (theme) => ({
    container: {
      flexGrow: 1,
      paddingTop: theme.spacing(4),
      paddingBottom: theme.spacing(2),
      paddingLeft: theme.spacing(2),
      paddingRight: theme.spacing(2),
    },   
  })
)
const App = function({ children }) {
    const style = useStyle(style)
    
    return (
      <View style={styles.container}>
            {/* content */}
      </View>
    )
}

withTheme props

import React, { Component } from 'react'
import  { withTheme } from '@material-native-ui/theme-provider'
import {
  NavigationContainer,
  DefaultTheme,
} from '@react-navigation/native';

class App extends Component {
  render() {
    const { styles, theme } = this.props
    const MyTheme = {
      ...DefaultTheme,
      colors: {
        ...DefaultTheme.colors,
        primary: theme.palette.primary,
      },
    };
    return (
      <NavigationContainer theme={MyTheme}>
            {/* content */}
      </NavigationContainer>
    )
  }
}

export default withTheme(App)

useTheme hook

import React, { Component } from 'react'
import {
  NavigationContainer,
  DefaultTheme,
} from '@react-navigation/native';
const App = function({ children }) {
    const theme = useTheme()
    const MyTheme = { //send theme to react navigation theme
      ...DefaultTheme,
      colors: {
        ...DefaultTheme.colors,
        primary: theme.palette.primary,
      },
    };
    return (
      
      <NavigationContainer theme={MyTheme}> 
            {/* content */}
      </NavigationContainer>
    )
}

with type script

import React, { Component } from 'react'
import { Text, TextStyle, TouchableOpacity, View, ViewStyle } from 'react-native'
import StyleSheet, { withStyles } from '@material-native-ui/theme-provider'

interface InterfaceStyles {
  container: ViewStyle
  button: ViewStyle
  actions: ViewStyle
  title: TextStyle
}

interface InterfaceProps {
  styles: InterfaceStyles
  changeTheme: Function
}

class App extends Component<InterfaceProps> {
  render() {
    const { styles, changeTheme } = this.props
    return (
      <View style={styles.container}>
        // children
      </View>
    )
  }
}

const style = StyleSheet.create(
  (theme): InterfaceStyles => ({
    //styles
  })
)
export default withStyles(style)(App)

customize

Use it in your components.

import Theme, { StylesConsumer, withStyles } from "@material-native-ui/theme-provider";

// with theme
const style = Theme.create((theme) => ({
  container: {
    color: theme.textColor,
    // Theme inherits all properties from StyleSheet
    ...Theme.absoluteFillObject,
  }
}));

// or without theme
const style = Theme.create({
  color: "blue",
});

// or create a stylesheet directly
// but do not pass this to style prop on consumer/hoc
const stylesheet = Theme.sheet({
  color: "blue",
})

// as consumer
const ThemedText = (props) => (
  <StylesConsumer style={style}>
    {(styles) => (
      <Text {...props} styles={styles} />
    )}
  </StylesConsumer>
);

export default ThemedText;

// or as hoc
const ThemedText = (({ styles, ...props }) => (
  <Text {...props} styles={styles} />
));

export default withStyles(style)(ThemedText);

Road map

state react-native react-native-web
fork from react-native-paint
provide theme as props
useStyle hook
useTheme hook
reWrite with type script

Example

About

React Native Theme a abstraction over StyleSheet.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published