Styling with React’s Material-UI v4 – Part 2

by | Aug 19, 2021 | 0 comments

import React from "react";
import { makeStyles, ThemeProvider } from "@material-ui/core/styles";

// Creating a basic theme object
// to hold our application styles.
const theme = {
  text: {
    color: "white",
    background: "deepskyblue"
  }
};

// Wrapping the entire application using the ThemeProvider,
// supplying it with the created theme object.
export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <ApplicationTree />
    </ThemeProvider>
  );
}
// Using the theme object to style our displayed text.
const useStyles = makeStyles((theme) => ({
  textClass: {
    background: theme.text.background,
    color: theme.text.color
  }
}));

// Using the generated class from the
// returned makeStyles hook
// on our div element.
const ApplicationTree = () => {
  const classes = useStyles();
  return <div className={classes.textClass}>
      I Read. You Learn.
    </div>;
};
Styling with React's Material-UI part 2
  text: {
    color: "white",
    background: "deepskyblue"
  }

The deep merge will take your theme object and will override only the styles and properties at the exact location needed.

For example, passing the following theme object will override only the property main inside the palette primary color:

const theme = createTheme({
  "palette": {
    "primary": {
      "main": "red"
     }
  }
});

// Result:
{
  // ...
  // default properties
  // ...
  palette: {
    primary: {
      light: "#7986cb"
      main: "red"
      dark: "#303f9f"
      contrastText: "#fff"
    }
  }
  // ...
  // other default properties
  // ...
}
// Missing "light","dark","contrastText"
{
  // ...
  // default properties
  // ...
  palette: {
    primary: {
      main: "red"
    }
  }
  // ...
  // other default properties
  // ...
}
const theme = createTheme({});
{ 
  breakpoints: Object
  direction: "ltr"
  mixins: Object
  overrides: Object
  palette: Object
  props: Object
  shadows: Array(25)
  typography: Object
  spacing: ƒ spacing() {}
  shape: Object
  transitions: Object
  zIndex: Object
}
const ApplicationTree = () => {
  return (
    <Button variant="contained" color="primary">
      I Read. You Learn
    </Button>
  );
};
Styling with React's Material-UI part 2 - Button Before
const theme = createTheme({
  // Using the "overrides" property
  // To override any style we want.
  overrides: {
    MuiButton: {
      containedPrimary: {
        backgroundColor: "red"
      }
    }
  }
});

export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <ApplicationTree />
    </ThemeProvider>
  );
}
Styling with React's Material-UI part 2 - Button After

If you are having trouble accessing nested child components, and you have not used makeStyles to style your component, then as a last resort you can access the classes you need by using regular SASS/CSS DOM classes, because the class names have not been suffixed with an identifier such as “MuiButton-root-16“,and the class name will be “MuiButton-root“.

// Accessing the outerTheme by passing a function.
<ThemeProvider theme={(outerTheme) => outerTheme}>
    <DeeplyNestedButton />
</ThemeProvider>
const applicationTheme = createTheme({
  overrides: {
    MuiButton: {
      containedPrimary: {
        backgroundColor: "red",
        color: "yellow"
      }
    },
    MuiFormLabel: {
      root: {
        color: "black"
      }
    }
  }
});
export default function App() {
  return (
    <ThemeProvider theme={applicationTheme}>
      <ApplicationTree />
    </ThemeProvider>
  );
}
// We wish to style this Material-UI
// Button with another theme.
const DeeplyNestedButton = () => {
  return (
    <Button variant="contained" color="primary">
      Deeply Nested Button
    </Button>
  );
};

const ApplicationTree = () => {
  return (
    <>
      <Button variant="contained" color="primary">
        I Read. You Learn
      </Button>
      <br /><br />
      <DeeplyNestedButton />
    </>
  );
};
Styling with React's Material-UI part 2 - Nested Themes 1
// Our new nested theme
const nestedTheme = createTheme({
  overrides: {
    MuiButton: {
      containedPrimary: {
        backgroundColor: "#98c379", // green
        color: "yellow"
      }
    }
  }
});

const ApplicationTree = () => {
  return (
    <>
      <Button variant="contained" color="primary">
        I Read. You Learn
      </Button>
      <br /><br />
      {/* Passing the nested theme here*/}
      <ThemeProvider theme={nestedTheme}>
        <DeeplyNestedButton />
      </ThemeProvider>
    </>
  );
};
// Missing the MuiFormLabel!
overrides: {
  MuiButton: { 
    containedPrimary: {
      backgroundColor: "#98c379"
      color: "yellow"
    }
  }
}
const ApplicationTree = () => {
  return (<>
...
...
<ThemeProvider 
theme={(outerTheme) => createTheme(outerTheme, nestedTheme)}>
        <DeeplyNestedButton />
</ThemeProvider>
...
..
</>);
};
Styling with React's Material-UI part 2 - Nested Themes 3
overrides: {
  MuiButton: { 
    containedPrimary: {
      backgroundColor: "#98c379"
      color: "yellow"
    }
  },
  MuiFormLabel {
    root {
      text: "black"
      color: "yellow"
    }
  }
}
const ApplicationTree = () => {
  return (<>
...
...
<ThemeProvider 
theme={(outerTheme) => createTheme({ ...outerTheme, nestedTheme })}>
        <DeeplyNestedButton />
</ThemeProvider>
...
...
</>);
};
const DeeplyNestedButton = () => {
// Directly accessing the theme,
// in this case the nestedTheme dissussed before,
  const theme = useTheme();
  return (
    <Button variant="contained" color="primary">
      Deeply Nested Button
    </Button>
  );
};
const applicationTheme = createTheme({
  props: {
    // Component Name - Search the Component API
    MuiButtonBase: {
     // Default prop to change
      disableRipple: true
    }
  }
})

You’ve made it!

This was another lengthy article, but I’m sure you are now able to theme your application with confidence.