make a custom class globally useable for material-ui

Viewed 2897

I found no single example on how to reuse classes using makeStyles() in material-ui.

Say I have a class called resizable or floating

I have to define makeStyles() inside every component which shares a specific class and duplicate the code.

The theming function does not provide any option to do this. All the theming examples show how to use the existing api props.

Maybe a context provider should be used to share styles? But wasn't the point of useTheme() exactly this? I don't understand why.

Anyone experienced with material-ui?

3 Answers

useTheme is a material-ui hook which only used to deal with material-ui themes.
I'm using this UI library for a few months and I also stuck in the same issue.

To deal with such a situation create your own custom hook which returns the classNames.

For example, here is a custom style hook which contains all the global classNames which is required:-

import { makeStyles } from '@material-ui/core/styles';

const globalUseStyles = makeStyles((theme) => ({
  redButton:{
    color:'red',
    background:'#fff',
    border:'1px solid red',
    '&:hover':{
      background:'red',
      color:'#fff'
    }
  },
  greentButton:{
    color:'green',
    background:'#fff',
    border:'1px solid green',
    '&:hover':{
      background:'green',
      color:'#fff'
    }
  }
}));

export default globalUseStyles

Now import this globalUseStyles hook and use it's classNames like below:-

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import globalUseStyles from './styleHooks';

const useStyles = makeStyles((theme) => ({
  root: {
    '& > *': {
      margin: theme.spacing(1),
    },
  },
  
}));

export default function ContainedButtons() {
  const classes = useStyles();
  const globalClasses = globalUseStyles()

  return (
    <div className={classes.root}>
      <Button className={globalClasses.greentButton} variant="contained">Green Button</Button>
      <Button className={globalClasses.redButton} variant="contained">
        Red Button
      </Button>
      <Button className={globalClasses.greentButton}>
        Green Button
      </Button>
      <Button variant="contained" color="primary">
        Default
      </Button>
    </div>
  );
}

Here is the working sandbox link:- https://codesandbox.io/s/nervous-water-miu0y

You need to use the <CSSBaseLine/> component of the Material UI to create global CSS styles for your app. According to the docs, wrap your components as following

<ThemeProvider theme={theme}>
<CSSBaseLine/>
{children}
<ThemeProvider />

Then using the createMuiTheme hooks you can create global styles by the following code

 import { createMuiTheme } from "@material-ui/core";
const theme = createMuiTheme({
  

  overrides: {
    MuiCssBaseline: {
      "@global": {
        ".subtitle": {
          color: "white",
          fontWeight: "bold",
          textTransform: "uppercase",
        },
      },
    },
  },
});

I finally got this to work! I think this solution is more straight forward in my opinion, I wanted to use custom classes on the MUI component. I didn't want to create a global style and have to import everywhere I needed it, my app is far along and this would be excruciating work to implement where needed. So I just use the good and old className to customize components.

My solution:

AppTheme.js

The solution is in the h2 node of the theme object where I added my custom class .page-title. I could simplify this down to show only my solution, but I'll leave a few extra properties to demonstrate what else you can do.

// You can define device sizes and use it in your theme object
const allDevices = "@media (min-width:320px) and  (max-width: 1024px)";
const allPhones = "@media (min-width:320px) and  (max-width: 767px)";
const portraitPhones = "@media (min-width:320px) and  (max-width: 480px)";
const landscapePhones = "@media (min-width:481px) and  (max-width: 767px)";
const tablets = "@media (min-width:768px) and  (max-width: 1024px)";

const MuiTheme = {
  palette: {
    primary: { main: "#E54E55" },
    secondary: { main: "#26B1EF" },
  },
  typography: {
    fontFamily: [
      "Montserrat",
      "Roboto",
      '"Helvetica Neue"',
      "Arial",
      "sans-serif",
    ].join(","),
    h1: {
      fontSize: "4rem",
      fontWeight: "700",
      [allPhones]: {
        fontSize: "3.2rem",
      },
    },
    h2: {
      fontSize: "3.5rem",
      fontWeight: "700",
      [allPhones]: {
        fontSize: "2.75rem",
      },
      "&.page-title": {
        marginBottom: "120px",
      },
    },
  },
  overrides: {
    // Style sheet name ⚛️
    MuiTypography: {
      // Name of the rule
      gutterBottom: {
        marginBottom: "20px",
      },
    },
    MuiTabs: {
      flexContainer: {
        borderBottom: "1px solid #ddd",
      },
      indicator: {
        height: "3px",
        borderRadius: "5px 5px 0 0",
      },
    },
    MuiButton: {
      sizeLarge: {
        paddingTop: "15px",
        paddingBottom: "15px",
      },
    },
  },
};

export default MuiTheme;

App.js

Then in your app you can add your custom theme like so:

import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import AppTheme from "./AppTheme";

<ThemeProvider theme={createTheme(AppTheme)}>
    Route and stuff ...
</ThemeProvider>;
Related