Material UI Lessons Learned

I’ve spent the last few weeks diving into Material UI. I’m building a Meteor app with React and Flow Router. So far, Meteor, React and Material UI have been a great mix. I received several pm’s after my first Material UI post.

I just wanted to share some of my experiences and I’m hoping other people will contribute their lessons learned.

  1. The Material UI docs are great but they are not always up-to date. There are some components missing such as the Enhanced button, switches and text areas. Also many components have additional features not listed. Any time I use a new component I go to the github source and look at the jsx file for the component. The propTypes usually give you a very clear picture of the available features. The src folder also has new components that are not in the docs.
  2. I’m new to React, but Material UI looks like it is well written. I think I’ve improved my own React programming by studying how they built their components.
  3. Flexbox works very well for laying out Material UI components. I’m using no bootstrap and no CSS except for a few lines for the root-props. I know inline styles are a bit controversial, but I find it much easier to debug.
  4. I switched from manually building Material UI with npm and browserify to izzilab:material-ui, because I was wasting time on build issues. The atmosphere package has been hassle free.
  5. To set a button as a link use
    linkButton={true}
    and you also have to set
    disableTouchRipple={true}
    Otherwise, the link takes 2 clicks.
  6. GridTiles don’t have a built in click handler so I use bind with onTouch Tap:
    onTouchTap={this._tileClick.bind(this, key)}
    Then use the key on the handler to reference which item was clicked.
  7. There are 2 different components for MenuItem one is in MUI and one is in MUI.Libs. They have slightly different functionality. The one in the docs is from MUI.Libs. I find the other one good for menu links.
  8. If you need to modify a component style that is not exposed, there are instructions here.
  9. All the Material Design icons are available. For example:
<SvgIcons.ActionAccountCircle color='Blue'/>```
10.  You can access your theme colors via the theme manager.  For example:
`backgroundColor={myTheme.palette.primary2Color}`

I hope this is helpful.
21 Likes

this is really helpful, thanks!

  1. There are 2 different components for MenuItem one is in MUI and one is in MUI.Libs. They have slightly different functionality. The one in the docs is from MUI.Libs. I find the other one good for menu links.

the material-ui project has just refactored menus to be composable. this is a breaking change on 14.0-rc2 atm

I switched … to izzilab:material-ui,

did you look at other packages? I needed to update material-ui source and found
markoshust/meteor-material-ui
an easier package to fork. but it exports mui not MUI
and some of the include paths seem to be different.

  1. You can access your theme colors via the theme manager. For example:
    backgroundColor={myTheme.palette.primary2Color}

I just battled with modifying a theme with the other package I was using without success.
using

getChildContext() {
  return {
    muiTheme: mui.Styles.ThemeManager.getMuiTheme(this.rawTheme)
  };
},

there is no theme available, and I think it maybe because I need to extend React Component, and I’m not sure how to do that…

do you have a pointer to a full example of how to extend a theme?

thanks!

@dcsan I picked izzilab:material-ui because it had the most stars. Also mrphu3074 has been very quick to respond with helpful answers to my questions. I have not had a reason to try any other packages.

do you have a pointer to a full example of how to extend a theme?

Have you looked at the Overriding Theme Variables section in the Customization docs. I haven’t tried it but it looks pretty straight forward if you need to change a specific component. Also I created a theme.jsx file to set all my theme defaults and colors. Here is the code:

var Spacing = MUI.Styles.Spacing;
var Colors = MUI.Styles.Colors;
var ColorManipulator = MUI.Utils.ColorManipulator;

myTheme = {
  spacing: Spacing,
  fontFamily: 'Roboto, sans-serif',
  palette: {
    primary1Color: Colors.cyan300,
    primary2Color: "#E22A23",
    primary3Color: Colors.lightBlack,
    accent1Color: Colors.yellow500,
    accent2Color: Colors.grey100,
    accent3Color: Colors.grey500,
    textColor: Colors.darkBlack,
    alternateTextColor: Colors.white,
    canvasColor: Colors.white,
    borderColor: Colors.grey300,
    disabledColor: ColorManipulator.fade(Colors.darkBlack, 0.3)
  }
};

I should also add how I load myTheme:

var { Styles } = MUI;
var { ThemeManager } = Styles;

MainLayout = React.createClass({
     childContextTypes: {
         muiTheme: React.PropTypes.object
    },
    getChildContext() {
        return {
            muiTheme: ThemeManager.getMuiTheme(myTheme)
        };
    },

Do you have any examples of how you used flexbox?

@uberom here is a good start - this is how I am rendering my main container

<AppCanvas>
         <Header />
           <div className="container-fluid">
                    <div className="row middle-xs">
                        <Paper className="col-sm-12">
                            <main className="box">{this.props.children}</main>
                        </Paper>
                    </div>
                </div>
            </AppCanvas>````

Flexbox is so easy and efficient, I'll never revert back to bootstrap solely for positioning elements anymore.

@etmarch, could you give a tip how did you connect Flexbox to react?
I’ve added it via npm, but can’t see css from it. Also I’ve tried react-flexbox-grid, but it also can’t see styles internally.

@sohaam I am using the FlexBoxGrid css library, and for quick prototyping I usually just link to the CDN from my apps head section. For production and using offline, the library is actually so small (one css file) that I just copied and pasted it into an internal style sheet.

I also tried react-flexbox-grid but couldnt get it working.

My newest dilemma with material-ui is not with the layout, but styling and decorating certain elements. For example, typography is pretty limited (material-ui doesnt come with custom styling for H elements, just use Roboto font) when compared to a more robust library like bootstrap or semantic-ui, which contains classes specifically for styling those elements.

1 Like

@etmarch, thanks for reply.
I’m currently searching a way to use FontAwesome in CardHeader instead of default icons, which is, in addition, doesn’t work “from the box”. Any ideas?

UPD: It was pretty simple:

avatar={
  <Avatar
    icon={
      <FontIcon
        className="fa fa-ticket"
       />
    }
  />
}

I use React inline styles.
Here is a flexbox example:

NotFound = React.createClass({
    render() {
        return (
            <div style={styles.errorContainer}>
                <SvgIcons.AlertError/>
                <span style={styles.errorMessage}>Page Not Found</span>
            </div>
        );
    }
});

const styles = {
    errorContainer: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'flex-start'
    },
    errorMessage: {
        marginLeft: '5px'
    }
};

All the styles for a component are contained within the component jsx file.

To use Font Awesome I would use kadira.dochead to load the font awesome cdn. Create a dochead.jsx file in client/lib and use the following code:

DocHead.addLink({
  rel: "stylesheet",
  type: "text/css",
  href: "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"
});

Then you can use fa in your FontIcon component:

<FontIcon className="fa fa-paw"/>

And to answer your question it would look like this for the card header:

<CardHeader
    title="My title"
    avatar= <FontIcon className="fa fa-paw"/>
    subtitle="My subtitle"/>
2 Likes

@etmarch, I’m interested in your styling findings. Please, share them with us later.)

There are many strong opinions regarding inline styles vs. css. I went inline because coupling the styles to the component seems like better modularity. I haven’t encountered any issues, and if I do I can always mix in some css. There is a good slide presentation by a Facebook engineer named Vjeux on the subject.

I should also add that Material UI has it’s own theme system which works well with inline.

@sohaam sure thing! Is there any specific pattern or element you have in mind? Material-UI facilitates inline styles with javascript, but applying classes from an external style sheet is still the same and works fine too.

I think its really about choosing one specific styling pattern, and remaining consistent throughout your app so you always know where the rules are written.

@etmarch, in fact it is not clear to me how to use their ThemeManager. For example, as you mentioned before, how to change font-family globally to, let’s say - Open Sans?
I tried figure it out by myself, but examples is not clear or too old

UPD: I find out how to set new global font. This approach helps.

I’ve added:

function modifyRawTheme(muiTheme, newFontFamily) {
  const {
    baseTheme,
    rawTheme,
    // add components you want recomputed here...
    ...other
    } = muiTheme;

  const newMuiTheme = getMuiTheme({
    ...baseTheme,
    fontFamily: newFontFamily
  });

  return {
    ...newMuiTheme,
    ...other
  };
}

and then in component:

getChildContext() {
  return {
    muiTheme: modifyRawTheme({}, "Open Sans")
  };
},
1 Like

I put these into my highest level component

  static get childContextTypes(){
    return{
      muiTheme: React.PropTypes.object
    };
  }

  getChildContext(){
    return {
      muiTheme: ThemeManager.getMuiTheme(MyRawTheme)
    };
  }
1 Like