Custom Material-UI Theme

Let’s create a new folder in the project’s root directory named shared . This folder is hold all the secondary code, starting with our custom Material-UI theme. Inside the shared folder, create another folder named MUI (short for Material-UI).

$ mkdir shared

$ cd shared

$ mkdir MUI

$ cd MUI

Next, we will create a file inside the MUI folder named theme.js . Inside this file, we will define some of the primary colors that we will be using throughout our app.

export const PRIMARY_COLOR = "#ed1d24";

export const PRIMARY_COLOR_TWO = "#9c7e7e";

export const PRIMARY_COLOR_THREE = "#e1bdbd";

export const ACCENT_COLOR_ONE = "#2b1256";

export const ACCENT_COLOR_TWO = "#ffae5b";

export const ACCENT_COLOR_THREE = "#ff6a6a";

With our basic colours defined, let’s another file named customMUI.js . This file is going to hold a React Higher Order Component. A Higher Order Component is a component that takes another component and injects some functionality inside it.

import React, {Component} from 'react';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

import getMuiTheme from 'material-ui/styles/getMuiTheme';

import Head from 'next/head';

import {

PRIMARY_COLOR,

PRIMARY_COLOR_TWO,

PRIMARY_COLOR_THREE,

ACCENT_COLOR_ONE,

ACCENT_COLOR_TWO,

ACCENT_COLOR_THREE

} from './theme';

material-ui contains a function named getMuiTheme that we are going to use to create our custom theme based on the color values that we had defined in theme.js file. We also need to make sure that the app that we are building loads the same code on server and the client.

We will start by creating a new const named customMaterialUI and define the HOC inside it. Inside this HOC, we will use the getInitialProps lifecycle hook that is provided to us by Next. getInitialProps give us a userAgent from the application’s environment.

const customMaterialUI = ComposedComponent => {

class HOC extends Component {

static async getInitialProps(ctx) {

const {req} = ctx;

const userAgent = req ? req.headers['user-agent'] : navigator.userAgent;

const subProps = await ComposedComponent.getInitialProps(ctx)

return {

...subProps,

userAgent

};

}

}

}

What’s happening here is that we are fetching the userAgent from either the server’s headers or if the app is running on client, we are fetching the userAgent from the navigator object. After that, we are creating a constant named subProps .

By using async await , we can wait for the the ComposedComponent ‘s props. Once we get those props, we need to return the userAgent and the ...subProps inside the HOC’s render function.

Next, we will work on the HOC’s render . We will use the getMuiTheme that we had imported from the material-ui library.

render() {

const {userAgent} = this.props;

const Lato = 'lato, sans-serif';

const muiTheme = getMuiTheme(

{

fontFamily: Lato,

palette: {

primary1Color: PRIMARY_COLOR,

primary2Color: PRIMARY_COLOR_TWO,

primary3Color: PRIMARY_COLOR_THREE,

accent1Color: ACCENT_COLOR_ONE,

accent2Color: ACCENT_COLOR_TWO,

accent3Color: ACCENT_COLOR_THREE

},

appBar: {

height: 30

}

},

{

userAgent

}

);

return;

}}

Most of this is simple. We are setting the Font Family to Lato, and defining the Palette with our 6 colors from theme.js . Along with that, we are setting the height of our appBar to a height of 30. Finally, we need to pass in the userAgent const that we get from our props.

One last thing left to do here. And that is the HOC’s return that is currently empty. Here, we will write a regular HTML file that we see almost everywhere. It will have a Head section which will have a link to the Google APIs in order to get the Lato Font Family. Only thing different here is that instead of a Body , we will use the MuiThemeProvider component that we had initially imported from the material-ui library.

MuiThemeProvider will wrap around our ComposedComponent and will be passed the muiTheme that we just created.