Make Awesome MUI Custom Buttons: Variants, Default Props, & More

The Material-UI (MUI) Button component merits a detailed exploration of all of its functionality. Its broad use across many UIs makes a deep knowledge of it’s props highly valuable.

In this MUI Button demo I will create a new button variant (a great new feature in v5!), enable all props on it, and use it as a link. I will also examine how to use new styling APIs with the Button.

Here’s a post on how to create a MenuButton, and here’s how to add MUI Badges to Buttons.

There is a Code Sandbox with full React code in the Resources section.

Here’s a link to a YouTube video version of this post, or watch it below:

Custom Button Variant

The foundation of our Material-UI Button is the custom variant that we’ll create.

I named my variant “bold” and gave it a simple styling of a relatively thick border and bold font. It’s nothing fancy:

Material-UI Button with Custom Variant
MUI Custom Button Variant

However, I noticed something unexpected when I created the new variant. The default color is no longer applied. I specified the black border, but text color should be whatever the theme or default palette.primary color is.

I attempted to add color using the color prop but was not successful. Because of this, I added a color to the variant.

const CustomTheme = createTheme({
  components: {
    MuiButton: {
      variants: [
        {
          props: { variant: "bold" },
          style: {
            fontWeight: "bold",
            border: `4px solid black`,
            color: "orange"
          }
        }
      ]      
    }
  }
});

All other default props seemed unaffected. I tested ripple, focus, and disabled and they worked great.

Regardless, the variant functionality in MUI v5 gives a great way to package up Button styling.

How to Extend MUI Type Definition for Custom Button Variants

If you create a new variant and you are using TypeScript, be sure to extend the Button Variant typing with the below code:

declare module "@mui/material/Button" {
  interface ButtonPropsVariantOverrides {
    bold: true;
  }
}

Notice I have simply added my ‘bold’ variant. This will now allow the Button to accept ‘bold’ as a string value for the variant prop.

Custom Default Props for the Material-UI Button

Another great new feature in MUI v5 is the ability to override the default values of props for a component across your theme. The defaultProps syntax is similar to variants and styleOverrides. It ‘lives’ inside theme.component.[component]:

const CustomTheme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        disableElevation: true,
        disableFocusRipple: true,
        disableRipple: true,
        endIcon: <Icon>star</Icon>
      }
    }
  }
});

I disabled the elevation and ripple props. I also added an endIcon simply to show it could be done as a default prop. Now all buttons using customTheme will have a star icon after their text:

MUI Button Default Props
MUI Button Default Props

Here’s the docs link if you want to learn more about default props.

All MUI Button Props Enabled

We have set some styling and props with the custom button variant and default props. Now I will enable the remaining props except for a few that conflict.

These are the props I enabled:

size="medium"
startIcon={<Icon>star</Icon>}
sx={{ mt: 2, ml: 2 }}
variant="bold"
href="smartdevpreneur.com"
  • size – MUI button size values can be “small”, “medium”, and “large” (plus custom string values according to the docs)
  • startIcon – similar to endIcon, but this injects an icon before the Button text
  • sx – this is a new styling prop in MUI 5. It accepts all CSS values plus additional styling MUI “system” values.
  • variant – this enables an existing or custom variant. I enabled our “bold” variant.
  • href – this accepts a string value that is expected to be a url. When enabled, it turns buttons into links. It also sets the root element to an anchor tag.

At this point our button is finished.

Material-UI Button with all props
MUI Button with all props

Here are the props I didn’t enable:

  • color – this didn’t play well with our custom variant so I set a value directly in the variant
  • classes – the sx prop essentially replaced this in Material-UI 5.
  • component – I could have used this to change the root component/element for Button, but the href prop was already setting the root to <a>. I checked just to be sure and it turns out the component prop will override the href prop.
  • disabled – this disables the button and I simply didn’t want to do that.
  • fullWidth – this conflicts with the size prop.

MUI ButtonUnstyled Component

Instead of creating a variant and removing default props, we could simply have started with a ButtonUnstyled component. It looks like this:

Material-UI ButtonUnstyled
MUI ButtonUnstyled

It is simply an HTML button element. We can set some props, like disabled, but not others, like size. Ripples are not toggled via prop either.

Use the new styled API for styling UnstyledButton components. It is an MUI adaptation of the styled-components library.

Resources

Code Sandbox link

Read how to align buttons here.

Read about Button onClick (with TypeScript) here.

Here’s how to Easily Disable a Button with JavaScript or CSS.

Button docs

Button API

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.