How to add custom Material UI palette colors
Asked Answered
U

5

50

I'm trying to establish my own palette colors to match my branding in Material UI. So far I can only get the primary and secondary colors to work when applied as the background color to buttons. When I add my own variable names, like use "accent" as shown as an example from Material UI's website, the button defaults to grey.

Here is my MyTheme.js code:

import { createMuiTheme } from 'material-ui/styles';
import purple from 'material-ui/colors/purple';

export default createMuiTheme({
    palette: {
        primary: { // works
          main: '#165788',
          contrastText: '#fff',
        },
        secondary: { // works
          main: '#69BE28',
          contrastText: '#fff',
        },
        companyBlue: { // doesn’t work - defaults to a grey button
            main: '#65CFE9',
            contrastText: '#fff',
        },
        companyRed: { // doesn’t work - grey button
            main: '#E44D69',
            contrastText: '#000',
        },
        accent: { // doesnt work - grey button
            main: purple, // import purple doesn’t work
            contrastText: '#000',
        },
    },
});

Here is my App.js code:

import React, { Component } from 'react';
import Button from 'material-ui/Button';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import MyTheme from './MyTheme';
import './App.css';
import { withStyles } from 'material-ui/styles';
import PropTypes from 'prop-types';


const styles = theme => ({
  button: {
    margin: theme.spacing.unit,
  },
  input: {
    display: 'none',
  },
});


class App extends Component {
  constructor(props)
  {
    super(props);
  }

  render() {
    const { classes } = this.props;
    return (
      <MuiThemeProvider theme={MyTheme}>
          <Button variant="raised" >
          Default
          </Button>
          <Button variant="raised" color="primary" className={classes.button}>
          Primary
          </Button>
          <Button variant="raised" color="secondary" className={classes.button}>
          Secondary
          </Button>
          <Button variant="raised" color="companyRed" className={classes.button}>
          Company Red
          </Button>
          <Button variant="raised" color="accent" className={classes.button}>
          Accent
          </Button>
      </MuiThemeProvider>
      );
  }
}

App.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(App);
Urethritis answered 27/4, 2018 at 20:17 Comment(1)
This is a strange one. Not sure what you mean by "purple" doesn't work, but you should have e.g. purple[500] or something in your MyTheme anyway.Sparrow
S
11

Other than needing to change purple in your MyTheme to be something like purple[500], I'm not sure why this wouldn't work for you. You may not be able override anything other than the primary and secondary in this way.

Regardless, here's a workaround:

In MyTheme.js:

accent: { backgroundColor: purple[500], color: '#000' }

Then in App.js:

<Button
  variant="raised"
  style={MyTheme.palette.accent}
  className={classes.primary}>
    Accent
</Button>

A working example is here.

Sparrow answered 27/4, 2018 at 20:53 Comment(4)
Hey Colin, I need my own variables to work with hex colors. The purple was just a test.Urethritis
Sure, but purple wasn't valid since it was an object.Sparrow
Thanks! I checked out your example and my custom colored variable works. For anyone looking at this post, here is the answer: <Button style={MyTheme.palette.companyRed} >Urethritis
and in your theme file change main to backgroundColor and contrastText to color.Urethritis
A
60

The Material UI palette is extendable, but you need to do a couple of things to create a new color and apply it to your Button component.

First, let’s define a theme with a custom color variable. You can use augmentColor() to generate the PaletteColor so it can be consumed in your Button:

import { purple } from "@mui/material/colors";

const { palette } = createTheme();
const theme = createTheme({
  palette: {
    myAwesomeColor: palette.augmentColor({ color: purple }),
    // Use this code if you want to use an arbitrary color
    // myAwesomeColor: palette.augmentColor({
    //   color: {
    //     main: "#00ff00"
    //   }
    // })
  }
});

Then update your TypeScript definition, so it can recognize the property myAwesomeColor when referencing the Palette and PaletteOption objects (skip this step if you're using JavaScript). You also need to extend the Button's color props definition, because by default it only accepts the following values:

'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning'
declare module "@mui/material/styles" {
  interface Palette {
    myAwesomeColor: string;
  }
  interface PaletteOptions {
    myAwesomeColor: string;
  }
}

declare module "@mui/material/Button" {
  interface ButtonPropsColorOverrides {
    myAwesomeColor: true;
  }
}

The final step is to inject the custom theme and set the custom color for your Button:

<ThemeProvider theme={theme}>
  <Button color="myAwesomeColor" variant="contained">
    AWESOME
  </Button>
</ThemeProvider>

Live Demo

Codesandbox Demo

Related answer

Alboin answered 21/9, 2021 at 6:24 Comment(9)
This worked for me when accessing the custom property inside of the callback of the styled function from @mui/material/styles. On the contrary, I get a "property doesnt exist" when accessing it through the returned value of the "useTheme" hook from @mui/material/styles. Any hints? :/Degression
@Degression Similar to this answer, put the component that uses useTheme inside ThemeProvider. See my updated codesandbox for reference.Alboin
@Alboin in your example (and mui's docs) you add a module augmentation specifically for buttons. I think most folks would like to add a color to the root(?) palette and watch it augment every mui component. Have you found a solution where you don't have to augment every component to get the color to be globally available?Dulcimer
@MattJones Anyone find a solution to adding a custom color to the to the root palette?Protease
The last step there "ButtonPropsColorOverrides", is not mentioned anywhere on the official site: mui.com/material-ui/customization/palette Took me ages to find your answer and solve my problem, so thank you very much!Holliehollifield
I always found it so weird you need to extend both Palette and PaletteOptions :(Sanguine
Using this solution, I'm getting TypeScript error: Object is possibly 'undefined'. ts(2352) when I try to reference the added palette color from the styled()(({ theme }) => ({ ... })) method. What type (if any) should I specify for the first curried function argument?Neddra
You sir are a god sent, I have been looking how to accomplish this for a solid two hours till I stumbled upon your answer.Nereen
I'm using create-react-app and I had to do export interface Palette extends MuiPalette {...} in my mui.d.ts in order to make the module augmentation successfully work.Reinhard
S
11

Other than needing to change purple in your MyTheme to be something like purple[500], I'm not sure why this wouldn't work for you. You may not be able override anything other than the primary and secondary in this way.

Regardless, here's a workaround:

In MyTheme.js:

accent: { backgroundColor: purple[500], color: '#000' }

Then in App.js:

<Button
  variant="raised"
  style={MyTheme.palette.accent}
  className={classes.primary}>
    Accent
</Button>

A working example is here.

Sparrow answered 27/4, 2018 at 20:53 Comment(4)
Hey Colin, I need my own variables to work with hex colors. The purple was just a test.Urethritis
Sure, but purple wasn't valid since it was an object.Sparrow
Thanks! I checked out your example and my custom colored variable works. For anyone looking at this post, here is the answer: <Button style={MyTheme.palette.companyRed} >Urethritis
and in your theme file change main to backgroundColor and contrastText to color.Urethritis
V
2

There shouldn't be a problem adding a custom palette as follows:

import { ThemeProvider, createTheme } from "@mui/material/styles";

const theme = createTheme({
  palette: {
    primary: {
      main: "#2a9461"
    },
    secondary: {
      main: "#494c7d"
    },
    companyRed: {
       main: "#E44D69",
       contrastText: "#000",
    },
  }
});

Using MUI colors like "purple" has to be accessed by the object key because each color comes with shade values from 50 to 900 (light to dark):

import { purple } from "@mui/material/colors";
import { ThemeProvider, createTheme } from "@mui/material/styles";

const theme = createTheme({
  palette: {
    primary: {
      main: "#2a9461"
    },
    secondary: {
      main: "#494c7d"
    },
    companyRed: {
       main: '#E44D69',
       contrastText: "#000",
    },
    accent: {
      main: purple[50] // Or purple[100], purple[200]
    }
  }
});

But if you are looking to create your own purple palette (and other colors) to match the branding, you can add a new js file with all custom colors and shades and import it in the main app:

colors.js file

export const green = {
  50: "#dbece2",
  100: "#a7d0b8",
  200: "#6eb18b",
  300: "#2a9461",
  400: "#008044",
  500: "#006c27",
  600: "#006020",
  700: "#005116",
  800: "#00410b",
  900: "#002700"
};
export const purple = {
  50: "#e9eaf0",
  100: "#c7cada",
  200: "#a3a8c1",
  300: "#8186a7",
  400: "#686c95",
  500: "#505485",
  600: "#494c7d",
  700: "#414371",
  800: "#393964",
  900: "#2d2a4c"
};
import { green, purple } from "./colors";
import { ThemeProvider, createTheme } from "@mui/material/styles";

const theme = createTheme({
  palette: {
    primary: {
      main: green[300]
    },
    secondary: {
      main: purple[600]
    },
    primaryLight: {
      main: green[50]
    }
  }
});

Here is a more detailed explanation of creating custom themes, palettes, and colors https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/

Vaginal answered 28/1, 2023 at 17:32 Comment(0)
S
0

for MUI v5 this seems to work for me:

let theme = createTheme({
  palette: { 
    customPrimary: {
      main: '#ff3402',
    },
  },
});


theme = createTheme(theme, {
  components: {
   MuiAppBar: {
      styleOverrides: {
        colorPrimary: {
          backgroundColor: theme.palette.customPrimary.main,
        },
      },
    },
}});
Stairwell answered 14/6, 2022 at 17:21 Comment(0)
S
0

For those creating a custom color in their theme in Typescript this is how I did it. I added the yellow and dark color types:

  interface Palette {
    dark?: Palette['primary'];
    yellow?: Palette['primary'];
  }
  interface PaletteOptions {
    dark?: PaletteOptions['primary'];
    yellow?: PaletteOptions['primary'];
  }
}

Then set them based on type. This took me a second to figure out. While I added dark a type on PaletteOptions, it's type then became like the rest as PaletteColorOptions which has the following type:

export type PaletteColorOptions = SimplePaletteColorOptions | ColorPartial;

export interface SimplePaletteColorOptions {
  light?: string;
  main: string;
  dark?: string;
  contrastText?: string;
}

So I used main to define the color in it's type.

const theme = createTheme({
dark: {
      main: '#5b504b'
    },
    yellow: {
      main: '#f4e6c2',
      dark: '#e1d7bd',
    }
}

Hope that helps anyone with the Typescript typing problem.

Sack answered 26/10, 2022 at 23:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.