Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add custom theme variable in createTheme()

By default the MUI theme is a combination of several pre-defined objects such as typography: {...}, palette: {...} etc.

Is is possible to add a custom object into this setup and still use createTheme?

So for example the theme object would become:

const theme = {
  palette: {
    primary: '#000'
  },
  typography: {
    body1: {
      fontFamily: 'Comic Sans'
    }
  },
  custom: {
    myOwnComponent: {
      margin: '10px 10px'
    }
  }
}
like image 996
Remi Avatar asked Sep 30 '19 13:09

Remi


Video Answer


2 Answers

Yes, this works just fine. Material-UI does a deep merge of its defaults with the object you provide with some special handling for keys that get merged in a more sophisticated fashion (such as palette, typography and a few others). Any unrecognized keys will come through unchanged.

Below is a working example:

import React from "react";
import ReactDOM from "react-dom";

import {
  useTheme,
  createMuiTheme,
  MuiThemeProvider
} from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#00F"
    }
  },
  typography: {
    body1: {
      fontFamily: "Comic Sans"
    }
  },
  custom: {
    myOwnComponent: {
      margin: "10px 10px",
      backgroundColor: "lightgreen"
    }
  }
});
const MyOwnComponent = () => {
  const theme = useTheme();
  return (
    <div style={theme.custom.myOwnComponent}>
      Here is my own component using a custom portion of the theme.
    </div>
  );
};
function App() {
  return (
    <MuiThemeProvider theme={theme}>
      <div className="App">
        <Button variant="contained" color="primary">
          <Typography variant="body1">
            Button using main theme color and font-family
          </Typography>
        </Button>
        <MyOwnComponent />
      </div>
    </MuiThemeProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit custom properties in theme

like image 66
Ryan Cogswell Avatar answered Sep 28 '22 08:09

Ryan Cogswell


You can add custom variables in your MUI theme as easy as:

const theme = createTheme({
  myField: {
    myNestedField: 'myValue',
  },
});

But if you're using Typescript, you also need to update the definition of ThemeOptions and Theme using module augmentation:

declare module '@mui/material/styles' {
  // fix the type error when referencing the Theme object in your styled component
  interface Theme {
    myField?: {
      myNestedField?: string;
    };
  }
  // fix the type error when calling `createTheme()` with a custom theme option
  interface ThemeOptions {
    myField?: {
      myNestedField?: string;
    };
  }
}

If you want to reuse the type between Theme and ThemeOptions, you can define a common interface and inherit it in both places:

declare module '@mui/material/styles' {
  interface CustomTheme {
    myField?: {
      myNestedField?: string;
    };
  }

  interface Theme extends CustomTheme {}
  interface ThemeOptions extends CustomTheme {}
}

Also note that you don't have to create custom variables in MUI theme if you want to override a custom component using createTheme(). See this answer for more detail.

Live Demo

Codesandbox Demo

like image 20
NearHuscarl Avatar answered Sep 28 '22 07:09

NearHuscarl