Giter Site home page Giter Site logo

theme's Introduction

Theme

The React Native component's style is usually defined as a static variable along with the component itself. This makes it easy to build self contained components that always look and behave in the same way. On the other hand, it complicates building themeable (or skinnable) components that could have multiple styles that can be customized without touching the component source code. @shoutem/theme is built to address that problem. With themes, you can target specific components in your app and customize them through one file, just like you would do it with CSS on the web.

Install

$ npm install --save @shoutem/theme

Docs

All the documentation is available on the Developer portal.

Community

Join our community on Facebook. Also, feel free to ask a question on Stack Overflow using "shoutem" tag.

Examples

Use Shoutem UI, set of components which are made to be customizable by Theme, to see how to work with it.

Create new React Native project:

$ react-native init HelloWorld

Install @shoutem/ui and @shoutem/theme and link them in your project:

$ cd HelloWorld
$ npm install --save @shoutem/ui
$ npm install --save @shoutem/theme
$ rnpm link

Now, simply copy the following to the App.js file of your React Native project:

import React, { Component } from 'react';
import { Dimensions } from 'react-native';
import { StyleProvider } from '@shoutem/theme';
import {
  Card,
  Image,
  View,
  Subtitle,
  Caption,
} from '@shoutem/ui';

const window = Dimensions.get('window');

const Colors = {
  BACKGROUND: '#ffffff',
  SHADOW: '#000000',
};

const MEDIUM_GUTTER = 15;

const theme = {
  'shoutem.ui.View': {
    '.h-center': {
      alignItems: 'center',
    },

    '.v-center': {
      justifyContent: 'center',
    },

    '.flexible': {
      flex: 1,
    },

    flexDirection: 'column',
  },

  'shoutem.ui.Card': {
    'shoutem.ui.View.content': {
      'shoutem.ui.Subtitle': {
        marginBottom: MEDIUM_GUTTER,
      },

      flex: 1,
      alignSelf: 'stretch',
      padding: 10,
    },

    width: (180 / 375) * window.width,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'flex-start',
    backgroundColor: Colors.BACKGROUND,
    borderRadius: 2,
    shadowColor: Colors.SHADOW,
    shadowOpacity: 0.1,
    shadowOffset: { width: 1, height: 1 },
  },

  'shoutem.ui.Image': {
    '.medium-wide': {
      width: (180 / 375) * window.width,
      height: 85,
    },

    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: Colors.BACKGROUND,
  },
};

export default class App extends Component<{}> {
  render() {
    return (
      <StyleProvider style={theme}>
        <View styleName="flexible vertical v-center h-center">
          <Card>
            <Image
              styleName="medium-wide"
              source={{ uri: 'http://shoutem.github.io/img/ui-toolkit/examples/image-12.png' }}
            />
            <View styleName="content">
              <Subtitle numberOfLines={4}>
                Lady Gaga Sings National Anthem at Super Bowl 50
              </Subtitle>
              <Caption>21 hours ago</Caption>
            </View>
          </Card>
        </View>
      </StyleProvider>
    );
  }
}

Finally, run the app!

$ react-native run-ios

Automated Testing

Jest has been set up to provide the ability to test @shoutem/theme after any changes.

To run tests, first add the following to dependencies in package.json:

  • "react-native": "0.63.2"
  • "react": "16.13.1"
  • "react-dom": "16.13.1"

Or whichever version is relevant after your changes. Then run npm i && npm run test and see if you broke anything.

UI Toolkit

Shoutem UI is a part of the Shoutem UI Toolkit that enables you to build professionally looking React Native apps with ease.

It consists of three libraries:

License

The BSD License Copyright (c) 2016-present, Shoutem

theme's People

Contributors

definitely-not-vlad avatar dependabot[bot] avatar domlazic avatar mrbr avatar sohotsoup avatar sstimac avatar tenodi avatar tomislav-arambasic avatar vunovati avatar zrumenjak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

theme's Issues

Button width mysterious when extending shoutem.ui.Button

So I'm extending the default shoutem theme, the relevant part is pasted below. It looks more or less good, but the buttons are mysteriously appearing wider than they should. It's as if they had the full-width styleName applied, or flex: 1, but they don't... Any ideas about what's happening here? Am I extending the theme wrong? I can't find a width or flex definition anywhere in the component structure (when inspecting with react-devtools).

The only reference to width anywhere is the layout state in the AnimatedComponent.

import { getTheme, defaultThemeVariables } from "@shoutem/ui";

const defaultTheme = getTheme({
  ...defaultThemeVariables,
  backgroundColor: colors.white
});
const Theme = {
  ...defaultTheme,
  "shoutem.ui.Button": {
    ...defaultTheme["shoutem.ui.Button"],
    backgroundColor: colors.primaryRed,
    paddingHorizontal: 30,
    paddingVertical: 2.5,
    borderRadius: 5,
    borderWidth: 2.5,
    borderColor: "transparent",
    ".secondary": {
      ...defaultTheme["shoutem.ui.Button"][".secondary"],
      borderColor: colors.primaryRed,
      borderWidth: 2.5,
      backgroundColor: 'transparent',
      "shoutem.ui.Text": {
        // ...defaultTheme["shoutem.ui.Button"][".secondary"]["shoutem.ui.Text"],
        color: defaultTheme["shoutem.ui.Text"].color
      }
    },
    "shoutem.ui.Text": {
      ...defaultTheme["shoutem.ui.Button"]["shoutem.ui.Text"],
      color: colors.white,
      fontSize: 17
    }
  }
};

export default Theme;

Hot reloading is not working

Hey,
I'm having an issue with my custom theme and hot reloading. If I change some values of my theme, f.e. the backgroundColor, I see a "Hot reloading..." message on my phones screen, but the changes are not reflected until I do a full reload of my app. Is there any workaround for this issue? It would be very nice for our workflow if we could see changes without doing a full reload of our app.

Overriding styles isn't working

Hey,
I'm trying to create a button component which changeable styles (border and without border). This is my React component:

class PlayerButton extends React.Component {

    constructor(props) {
        super(props);


    }


    render() {



        return (
            <TouchableOpacity style={this.props.style.buttons} styleName={this.props.styleName}>
                    <Icon styleName="icon big" name={this.props.icon} size={this.props.iconSize}/>
            </TouchableOpacity>
        );
    }

}


let style = {
    buttons: {}
};

let styled = connectStyle("musica.Player", style)(PlayerButton);


export {styled as default};

This is the part of my theme where I've defined the values:

    buttons: {


        '.no-border': {
            borderWidth:0
        },

        '.big': {
            width: 60,
            height: 60,
            borderRadius: 60,

        },


        '.mid': {
            width: 40,
            height: 40,
            borderRadius: 40
        },


        borderWidth:1,
        borderStyle:'solid',
        borderColor:'#585858',

        justifyContent:'center',
        alignItems:'center',
        marginHorizontal: 10
    }

In another component, I'm doing something like this:

The problem is, that the border is still there, so borderWidth:0 is ignored. I've also tried it with another properties like backgroundColor, there I have the same effect. The default value doesn't get overridden.

Styling based on multiple styleNames

Hey there, nice work. It's a very useful library.

I want to know if it's possible to do apply different styles to a component according to combination of styleNames. For example, I want different styles for a button in these cases:

<Button bordered />
<Button danger />
<Button bordered danger />

This is what I would do considering CSS kind of styling:

'components.Button': {
  '.bordered': {
    borderWidth: 1,
    borderColor: 'blue',
    backgroundColor: 'transparent',
    'components.Text': {
      color: 'blue',
    },
  },
  '.danger': {
    borderWidth: 0,
    backgroundColor: 'red',
    'components.Text': {
      color: 'white',
    },
  },
  '.bordered.danger': {
    borderWidth: 1,
    borderColor: 'red',
    backgroundColor: 'transparent',
    'components.Text': {
      color: 'red',
    },
  },
}
  

build crash Parallax.js doesnt exist

Wanted to test this today, created new project:

  "dependencies": {
    "@shoutem/theme": "^0.8.7",
    "@shoutem/ui": "^0.9.1",
    "react": "15.4.1",
    "react-native": "0.38.0"

threw this build error on ios:
image

Cannot read property 'example' of undefined

I'm getting the error Cannot read property 'container' of undefined, from a presentation container that's wrapped by a data container and a StyleProvider. I've read through the documentation and the example, but it doesn't match exactly what I'm doing (and it's done very differently here, here, and here)

It's something like this (simplified):

Styles

const styles = {
  container: {
    flex: 1,
    width: 100,
  }
}

export default styles;

Data

import {Component} from 'react';
import theme from './theme';
import PrettyContainer from './PrettyContainer';
import styles from './styles';

class DataContainer extends Component{
  //other stuff...
  render(){
    <StyleProvider style={theme}
      <PrettyContainer/>
    </StyleProvider
  }
}

export default connectStyle('my.layout.DataContainer', styles)(SignInContainer);

And the PrettyContainer

const PrettyContainer = (props)=>{
  const {style} = props;
  return  <View style={style.container}/>;
}

export default PrettyContainer;

NavigationBar keeps overriding my status bar color

<View style={container}>
        <StatusBarComponent backgroundColor='#fff' barStyle="dark-content" />

        <View
          style={{
            width: width / 1.2,
            marginBottom: width / 5,
          }}
        >
          <NavigationBar
            style={{
              zIndex: 1,
              padding: 20
            }}

            leftComponent={
              <Title
                onPress={() => this.openSearchModalForMyLocation()}
              >
                FROM
              </Title>
            }

            centerComponent={
              <Title
                onPress={() => this.openSearchModalForMyDestination()}
              >
                TO
              </Title>
            }

            rightComponent={
              <DropDownMenu
                options={this.state.filters}
                selectedOption={this.state.selectedSlot ? this.state.selectedSlot : this.state.filters[0]}
                onOptionSelected={(filter) => this.setState({ selectedSlot: filter }, () => this.calculatePrice())}
                titleProperty="name"
                valueProperty="value"
                visibleOptions={5}
                vertical
              />
            }
          />
        </View>
</View>

Add ability pass an array of styles

Sometimes I need to change the style of a component in inline mode by setting the prop style. This works, but it is not possible to pass an array of objects to prop style, as you can with the normal components of react native.

Can you add this possibility?
Thanks

0.11.4 performance improvement is also a regression

In my app I have a light and dark mode, and when that changes, I pass in an updated theme object to StyleProvider, thus re-rendering all the connected UI elements.

Unfortunately, this was broken by this commit: 5b1638e

I quite like being able to update the theme with dynamic values, and would rather handle the performance optimization myself. If that's not possible, then a forceUpdate function or something would be great.

error: bundling: UnableToResolveError: Unable to resolve module `./examples/Shapes`

Getting this

error: bundling: UnableToResolveError: Unable to resolve module `./examples/Shapes`

/node_modules/@shoutem/theme/examples/Shapes doesn't exist

The problem is i dont have an examples folder that is referenced in index.js

import connectStyle from './src/connectStyle';
import { INCLUDE } from './src/resolveIncludes';
import StyleProvider from './src/StyleProvider';
import Theme, { ThemeShape } from './src/Theme';
import { createVariations, createSharedStyle } from './src/addons';
import Shapes from './examples/Shapes';

const Examples = {
  Shapes,
};

export {
  connectStyle,
  INCLUDE,
  StyleProvider,
  Theme,
  ThemeShape,
  createVariations,
  createSharedStyle,
  Examples
};

from package.json

  "name": "@shoutem/theme",
  "version": "0.8.8",
  "main": "index.js",

Any ideas?

Overriding styles not working / theme not being applied

Hi there, I'm having trouble getting themes to work:

I have this component:

export default class App extends Component<*, State> {
    render() {
        return (
            <StyleProvider theme={{}}>
                <SafeAreaView style={{ flex: 1 }}>
                    <Test/>
                </SafeAreaView>
            </StyleProvider>
        );
    }
}

That tries to use the Test component:

class _Test extends React.Component<{
    style: Object
}> {
    render() {
        const styles = this.props.style;

        return <View style={styles.test}>
            <Text>TEST</Text>
        </View>;
    }
}

const Test = connectStyle('test', {
    test: {
        backgroundColor: 'red'
    }
})(_Test);

As is, the element gets rendered with a red background.

When I try to change the theme's color, nothing happens:


export default class App extends Component<*, State> {
    render() {
        return (
            <StyleProvider theme={{
                'test': {
                    test: {
                        backgroundColor: 'green'
                    },

                    backgroundColor: 'green'
                }
            }}>
                <SafeAreaView style={{ flex: 1 }}>
                    <Test/>
                </SafeAreaView>
            </StyleProvider>
        );
    }
}

What am I doing wrong? I've followed everything the docs said.

warning failed prop type: invalid prop backgroundColor supplied to View : this.state.buttoncolor

I got an issue here, Hope you can help me in this situation here is my code.

const routes = [
  {
      value:"Daily Time Record",
      datavalue:"Home",
      buttoncolors:"this.state.buttoncolor"
  },
  {
     value:"Personal Info",
     datavalue: "EmployeePersonalInfo",
     buttoncolors:"this.state.buttoncolor1"
   },
   {
     value:"Employment Info",
     datavalue: "EmploymentInfo",
     buttoncolors:"this.state.buttoncolor2"
   }
 ];

export default class SideBar extends React.Component {
  constructor(props){
    super(props);
    this.state={
      buttoncolor:'white',
      buttoncolor1:'gray',
      buttoncolor1:'blue'
    };
  }


  render() {
    return (
      <View style={{
        width:300,
        height:540,
        backgroundColor:'#212223'
      }}>

        <Header style={{
          height:100,
          backgroundColor:'#212223',
          justifyContent:'flex-start',
          alignItems:'center',
          borderBottomWidth:1,
          borderBottomColor:'black',
        }}>
          <Title>Juan De la cruz</Title>
        </Header>
        
        <View style={{width:300,height:165}}>
          <List style={{marginLeft:-17}}
            dataArray={routes}
            renderRow={data => {
              return (
                <ListItem style={{
                    backgroundColor:'#212223',
                    borderColor:'black',
                    borderBottomWidth:1
                  }}
                  button style={{backgroundColor:data.buttoncolors}}
                  onPress={() => this.props.navigation.navigate(data.datavalue)}
                >
                  <Body>
                    <Text style={{color:'white'}}>{data.value}</Text>
                  </Body>
                  <Right>
                    <Icon name="ios-arrow-forward" />
                  </Right>
                </ListItem>
              );
            }}
          <List />
        </View>

      </View>
    );
  }
}

ref warnings on stateless styled components

I'm getting ref warnings on my styled stateless components, like so:
screen shot 2017-04-18 at 8 17 36 am
I think it has to do with the order of ref and addedProps, but I'm not sure. I tried it with the withRef option set to true and false, neither seemed to help.
Ideas? It's just kind of annoying. I'm on the latest versions of everything (rn 0.43.3, @shoutem/theme 0.9.0)

All default rules lost?

<StyleProvider style={theme}> <Screen> <NavigationBar styleName="inline" leftComponent={ <Button onPress={() => this.props.navigation.navigate("DrawerOpen")}> <Icon name="sidebar"/> </Button> } centerComponent={ <Title> {this.renderDate()} </Title> } rightComponent={ <Button onPress={() => this.setState({isTimelineOpen: true})}> <Icon name="history"/> </Button> } /> </Screen> </StyleProvider>

theme is an empty object, all default rules from shoutem ui seems to have lost. Any help?

Adding styles with the default ones

Hello,
I want to expand the Overlay style to include backgroundColor: 'rgba(0, 0, 0, 0.7)'.
The problem is, when I define the theme like this:

const theme = {
    ...getTheme(),
    'shoutem.ui.Overlay': {
        '.darker': {
            backgroundColor: 'rgba(0, 0, 0, 0.7)'
        }
    }
}

It overrides the Overlay styles totally.
How can I keep the default styles and just override the backgroundColor definition?

Live theme editor

This is feature request. I was looking at available UI toolkits for RN, and I'm surprised that I haven't seen an evidence of live theme editor in any of them (have I missed one ?)

The idea is following: you have an app with all available UI elements from shoutem ui kit, you open it inside emulator, and you can click on any element and live-edit it's styles (including editing style variables that are used in different places) in pop-up that appeared. And in the end you can export file with generated styles.
At first sight I'd say that it's quite easy to implement, especially if you're maintainer of UI kit like shoutem, but even if it's hard - I think such editor absolutely worth it.

How to extend theme?

Hey,
I'm trying to extend the default theme with my own changes.

app.js

   render() {
        return (
            <StyleProvider theme={theme}>
                <View style={ViewStyles.standard}>
                    <Router>
                        <Scene key="start" component={Start} hideNavBar={true}/>
                        <Scene key="login" component={Login}/>
                    </Router>
                </View>
            </StyleProvider>
        );
    }


const theme = _.merge(getTheme(),{
    'shoutem.ui.Text': {
        '.desc': {
            marginVertical: 30,
            textAlign:'center',
            fontFamily:'OpenSans-Regular',
            color: 'white'
        },

        '.login': {
            marginTop:20,
            'shoutem.ui.Icon': {
                color: '#00D1FF',
                margin: 0
            }
        },

        color: 'white'

    }
});

In my start component, I have something like this:

start.js

   render() {

        return (

             <View style={ViewStyles.standard}>

                 <Image
                     source={require('../../images/start_bg.png')} style={styles.imageWrapper}/>

                 <View style={styles.contentView}>
                     <Image source={require('../../images/logo_mid.png')} style={styles.logo}/>
                     <Text styleName="desc">This is a demo text</Text>
                 </View>
             </View>
        );
    }

Problem is that the style isn't applied, my text color is still black instead of white.

Slow performance on Android

First of all! A huge thanks for this repo. I was going to build my own styling engine and then I stumbled upon this repo.

I am Sanket from the NativeBase team and with the latest version of NativeBase 2.0 we have used shoutem/theme as the core styling engine for our components.

We have realized that the performance on Android is really slow on complex pages and the bottleneck lies in the resolveComponentStyle file where the actual merge happens. Any solution for that?

Border radius shouldn't be normalized

React native's <Image> element doesn't support specifying border radius for each individual corner so if we normalize border radius it will not be properly applied to <Image> elements.

PropTypes should be imported from 'prop-types'

I can see that PropTypes are being imported from 'prop-types' in develop, but in the latest release they're still being imported from 'react'. This is throwing errors all over the place in my app! Please could you tag a new which includes these changes?

Explain how to pass props, or make it possible, with connectStyle

So I'm using connectStyle all over the place, which is cool (I like the idea of it), but I'm having trouble with props not being passed through. For example I wrap a container like so:

export default connectStyle('project.component.ProjectTabs', styles)(ProjectTabs);

and then when I do this elsewhere:

render(){
  <ProjectTabs someProperty="somevalue"/>
}

someProperty is not passed along to ProjectTabs (because, I suspect, the secret style component actually receives them, and isn't passing them along). Can you confirm this, or tell me what the proper way to pass the props through is, if you have one?

How can I append to default theme instead of overriding?

Hello,

It seems that when passing a theme to StyleProvider it overrides the themed widget completely.
For example if I have the following:

const theme = {
  'shoutem.ui.Screen': {
    backgroundColor: 'grey',
  },
}

Most widgets in shoutem.ui will look pretty bad, if they are inside a <Screen> component, because the Screen component looses it's default styles and only has backgroundColor: 'grey'.

Is there a way to extend the base theme in my custom theme and override or add new attributes to it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.