react-native-styleman

0.4.5 • Public • Published

React Native Styleman

license

React Native Styleman is a tiny(3KB gzipped), high performance responsive styling library for react native.

It provides following features:

  • Static and dynamic theming with support for global theme variables.
  • Media Queries with support for -> [width, height, orientation, direction, platform, platformVersion]
  • Responsive units to automatically scale the UI based on the device's screen size.
  • Dynamic styling based on device's orientation.
  • Highly Extendable: Add your own custom css properties and values.

Installation

Use following command to install the library

npm install react-native-styleman

OR if you are using yarn, then:

yarn add react-native-styleman

Usage

Basic usage

Defining your Theme Data and wrap your root component in StyleManProvider.

import { StyleManProvider } from 'react-native-styleman';
import { MainComponent } from './MainComponent'; // <-- our root component 
 
// create your theme data here... 
const THEME_DATA = () => ({
    
    DEFAULT_BACKGROUND: 'white',
    
    // typography
    SMALL: 8,
    MEDIUM: 15,
    LARGE: 22,
    // text colors
    PRIMARY: 'blue'
});
 
// then pass the THEME_DATA to StyleManProvider as a prop and pass you root component as its child.
const App = () => {
    return (
        (
            <StyleManProvider theme={THEME_DATA}>
                <MainComponent />
            </StyleManProvider>
        )
    );
};
// later 
// AppRegistry.registerComponent('yourApp', () => App);

Remember, you just have to use the StyleManProvider at the root level only.

Now lets add some styles to the MainComponent

// first import `withStyles` higher order component from `react-native-styleman`
import { withStyles } from 'react-native-styleman';
import { View, Text } from 'react-native';
 
// now lets write styles for the MainComponent using the variables created in the theme object.  
const styles = ({ MEDIUM, PRIMARY }) => ({
    // here we are destructuring the object returned by THEME_DATA function 
    // and getting the variables MEDIUM_LARGE and PRIMARY out of it.
       
    container: {
        flex: 1
    },
    text: {
        color: PRIMARY, // using theme here
        fontSize: MEDIUM, // and here too
    }
});
 
// Now lets define out MainComponent  
let MainComponent = ({ styles })=>(
  // here we get our styles in the props.
  // `withStyles` function(mentioned below) auto injects the styles in the props of the component.
    <View style={styles.container}>
        <Text style={styles.text}> Hello World </Text>
    </View>
);
 
// now, lets wire up things together.
MainComponent = withStyles(styles)(MainComponent);
 
export { MainComponent };

We don't need to wrap the child components of MainComponent in StyleManProvider again. We can just use the withStyles function to consume their styles in those components.

Now lets change component's style on orientation change automatically

Now lets say we want to change the font color based on the orientation of the device. Here is how we can do that:

 const styles = () => {
    return ({
        container: {
            ...
        },
        text: {
            //more styles...
            fontSize: 22,
            color: 'blue',//default// <---------------| // this value would be overwritten 
                                   //                 | // based on current orientation of 
            '@media': [            //                 | // the device. When the device is in 
              {                    //                 | // landscape mode, it would be overwritten 
                orientation: 'landscape',//           | // to red and to pink in portrait mode
                styles: {          //                 |
                  color: 'red', //--------------------|
                }
              },
              {                    
                orientation: 'portrait',
                platform: 'android',  // we can add more than one constraint 
                styles: {          
                  color: 'pink'
                  
                  // any other styles that we write here would also be merged to the `text` object's style
                  // if the device is an android as well as in portrait mode.
                }
              }
            ] // as you can see `@media` accepts an array with multiple queries. 
              // Styleman would process these queries from top to bottom. 
              // Styles for a query is applied if all the constraints given in it are true 
              // (in that case rest of the queries are not processed)      
        }
    });
};
 
let MainComponent = ({ styles })=>(
    <View style={styles.container}>
        <Text style={styles.text}> Hello World </Text>
    </View>
);
 
// now, lets wire up things together.
MainComponent = withStyles(styles)(MainComponent);
 
export { MainComponent };

Following properties are supported by @media:

{
    platform:     'ios' | 'android',
    minVersion:   number<float>, // min version of ios/android 
    maxVersion:   number<float>, // max version of ios/android
    minWidth:     number, // in DP  
    maxWidth:     number, // in DP
    minHeight:    number, // in DP
    maxHeight:    number, // in DP
    orientation: 'landscape' | 'portrait',
    direction:   'rtl' | 'ltr',
}

Responsive units

Instead of adjusting certain properties like fontSize manually based on the screen size we can automate it. We can do this via responsive units.

Responsive units are functions which take some static value and return another values based on usually screen dimensions. eg: Let's say that on a 320dp with screen you may want the font size to be 14dp but want to increase it on a bigger screens (420dp screen) and reduce it on lower dp screens (240 dp) automatically. This can be achieved via Responsive units. You can read more about it here

We currently have following responsive units:

  • rem: responsive em (for horizontal usecases, scales linearly)
  • mrem: moderately rem (for horizontal usecases, but scales moderately)
  • vrem: vertically rem (for vertical usecases, scales linearly)
  • mvrem: moderately vrem (for vertical usecases, but scales moderately)

Lets jump into code:

const THEME_DATA = function ({
   getRem, 
   getMRem,
   getScreenWidthDP, // -> returns the screen width in DP
}){
 // in arguments, we get these `value processor` generators. Once generated, these functions process values given to them.   
 // we can configure these to get our units
   const rem = getRem(getScreenWidthDP(), 320); // 320 is the width of the screen in the given designs to you by your designer. 
   const moderateScaleFactor = 0.4;  // here we are saying, we want to keep the scaling to 40% of the original value only
   const mrem = getMRem(getScreenWidthDP(), 320, moderateScaleFactor);
 
   return {
       // units function
       rem, // <- passing these functions to our theme object so that we can access these from any stylesheet. 
       mrem,
       
       // typography
       SMALL: rem(8),
       MEDIUM: rem(15),
       LARGE: rem(22),
   };
};
 
// now lets access `mrem` from the theme object
const styles = ({ MEDIUM, mrem })=>{
   return ({
       container: {
           flex: 1
       },
       text: {
           fontSize: mrem(MEDIUM) // lets make the fontSize of this text scale as per the device with.
       }
   });
};
 
let MainComponent = ({ styles })=>(
   <View style={styles.container}>
       <Text style={styles.text}> Hello World </Text>
   </View>
);
 
MainComponent = withStyles(styles)(MainComponent);
 
const App = () => {
   return (
       (
           <StyleManProvider theme={THEME_DATA}>
               <MainComponent />
           </StyleManProvider>
       )
   );
};
 

react-native-styleman supports following value processors generators:

  • getScreenWidthDP() returns -> width
  • getScreenHeightDP() returns -> height
  • getScreenWidthPX() returns -> width
  • getScreenHeightPX() returns -> height
  • getRem(SCREEN_WIDTH_DP, DESIGN_GUIDELINES_BASE_WIDTH_DP) returns -> fn(width)
  • getMRem(SCREEN_WIDTH_DP, DESIGN_GUIDELINES_BASE_WIDTH_DP, MODERATE_SCALING_FACTOR) returns -> fn(width)
  • getVRem(SCREEN_HEIGHT_DP, DESIGN_GUIDELINES_BASE_HEIGHT_DP) returns -> fn(height)
  • getRound() returns -> fn(height|width)

Switching theme dynamically

Let's see now how we can change the theme dynamically with an example: eg: Let's say you want to change the PRIMARY at runtime from blue to red when the Change Theme button is clicked.

 
// your original theme data. 
const THEME_DATA = () => ({
    // typography
    SMALL: 8,
    MEDIUM: 15,
    LARGE: 22,
    // text colors
    PRIMARY: 'blue' // change this to red 
});
 
const App = () => {
    return (
        (
            <StyleManProvider theme={THEME_DATA}>
                <MainComponent />
            </StyleManProvider>
        )
    );
};
  
const styles = ({ LARGE, PRIMARY }) => ({       
    container: {
        flex: 1,
    },
    text: {
        color: PRIMARY, // using theme here
        fontSize: LARGE, // and here too
    }
});
 
// the `withStyles` HOC along with styles also passes few helper functions like `setTheme` and `getTheme`   
let MainComponent = ({ styles, setTheme })=>( 
    <View style={styles.container}>
        <Text style={styles.text}> Hello World </Text>
       
        <Button title={"Change Theme"} onPress={() => {
                    setTheme((valProcessors) => {
                        // Get the current system theme. 
                        const baseTheme = THEME_DATA(valProcessors);
                        
                        // update it as per our liking and return it.  
                        return {
                            ...baseTheme,
                            PRIMARY: 'red'
                        }
                    });
                }} />
    </View>
);
 
// now, lets wire up things together.
MainComponent = withStyles(styles)(MainComponent);
 
export { MainComponent };

The withStyles HOC passes following props to the wrapper component:

  • styles
  • setTheme(themeGeneratorFunction)
  • getTheme() -> returns current processed theme

themeGeneratorFunction: (valueProcessors) -> newThemeObject In case you didn't noticed the StyleManProvider's theme prop also accepts a themeGeneratorFunction.

Inspiration

This library is inspired from following projects:

License

MIT @ Anubhav Gupta

Package Sidebar

Install

npm i react-native-styleman

Weekly Downloads

1

Version

0.4.5

License

MIT

Unpacked Size

150 kB

Total Files

46

Last publish

Collaborators

  • anubhavgupta