How to keep the background color of disabled Button in Material-UI?

Viewed 5008

I want to change the global style of the disabled Button component from Material-UI. But the problem is I am unable to keep the original color scheme of the button.

Consider this button:

<Button color="secondary" disabled={isLoading}>Create Account</Button>

Now by default Mui-disabled would be attached to this button. Whose color and the background-color are taken from theme.palatte.action property. So this disabled button would be having CSS as:

color: rgba(0,0,0,0.26);
box-shadow: none;
background-color: rgba(0,0,0,0.12);

But I want my disabled button to maintain its original color ("primary, secondary", "error" etc.) added with an opacity of 0.7. By default, the cursor events are set to none by MUI.

I tried it using the custom theme but I don't know how to maintain the original color of the button. E.g if the Button is primary keep the primary color, if the Button is secondary keep the secondary colors.

    MuiButton: {
        styleOverrides: {
            root: {
                textTransform: "none",
                boxShadow: "none",
                "&.Mui-disabled": {
                    // background: "initial",
                    // color: "initial",
                    opacity: .7
                }
            },
        }
    }

Of course, I don't want to write a custom code for each code. I can do this even by creating a wrapper around the MUI's button and use that wrapper everywhere in my code. But I want to do it the MUI way by overriding the theme.

How can I implement a global solution?

2 Answers

Is this what you want? just don't set the disabledBackground color in the palette:

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

const defaultTheme = createTheme();
const theme = createTheme({
  palette: {
    action: {
      disabledBackground: "", // don't set the disable background color
      disabled: "white", // set the disable foreground color
    }
  },
  components: {
    MuiButtonBase: {
      styleOverrides: {
        root: {
          [`&.${buttonClasses.disabled}`]: {
            opacity: 0.5
          },
          // Fix ButtonGroup disabled styles.
          [`&.${toggleButtonClasses.root}.${buttonClasses.disabled}`]: {
            color: defaultTheme.palette.action.disabled,
            borderColor: defaultTheme.palette.action.disabledBackground
          }
        }
      }
    }
  }
);

At the current time I'm writing. There is also other components that reuses the disableBackground property, make sure you take a look and are okay with that too. I display them all in the example below.

Live Demo

Codesandbox Demo

With the way that the disabled state is handled in the default styles, I think you need to redefine the default colors within your override in order for it to work.

In the source code you can find how the default colors are defined for the text, outlined, and contained variants.

The example below demonstrates overriding the disabled styles for all three variants with opacity: 0.7 by redefining the non-disabled colors within the "&.Mui-disabled" style overrides.

import * as React from "react";
import Stack from "@mui/material/Stack";
import Button from "@mui/material/Button";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { alpha } from "@mui/system";
const defaultTheme = createTheme();
const colors = [
  "inherit",
  "primary",
  "secondary",
  "success",
  "error",
  "info",
  "warning"
];
const containedColorStyles = {};
const textColorStyles = {};
const outlinedColorStyles = {};
function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}
colors.forEach((color) => {
  containedColorStyles[`&.MuiButton-contained${capitalizeFirstLetter(color)}`] =
    color === "inherit"
      ? {
          backgroundColor: defaultTheme.palette.grey[300],
          color: defaultTheme.palette.getContrastText(
            defaultTheme.palette.grey[300]
          )
        }
      : {
          backgroundColor: defaultTheme.palette[color].main,
          color: defaultTheme.palette[color].contrastText
        };
  textColorStyles[`&.MuiButton-text${capitalizeFirstLetter(color)}`] =
    color === "inherit"
      ? {
          color: "inherit"
        }
      : {
          color: defaultTheme.palette[color].main
        };
  outlinedColorStyles[`&.MuiButton-outlined${capitalizeFirstLetter(color)}`] =
    color === "inherit"
      ? {
          color: "inherit",
          borderColor:
            defaultTheme.palette.mode === "light"
              ? "rgba(0, 0, 0, 0.23)"
              : "rgba(255, 255, 255, 0.23)"
        }
      : {
          color: defaultTheme.palette[color].main,
          borderColor: `${alpha(defaultTheme.palette[color].main, 0.5)}`
        };
});
const theme = createTheme({
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          textTransform: "none",
          boxShadow: "none",
          "&.Mui-disabled": {
            ...containedColorStyles,
            ...textColorStyles,
            ...outlinedColorStyles,
            opacity: 0.7
          }
        }
      }
    }
  }
});
export default function ColorButtons() {
  const variants = ["text", "outlined", "contained"];
  return (
    <ThemeProvider theme={theme}>
      {variants.map((variant) => (
        <div key={variant}>
          {capitalizeFirstLetter(variant)} Variant
          <Stack direction="row" spacing={2}>
            {colors.map((color) => (
              <Button key={color} variant={variant} color={color}>
                {capitalizeFirstLetter(color)}
              </Button>
            ))}
          </Stack>
          Disabled {capitalizeFirstLetter(variant)} Variant
          <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
            {colors.map((color) => (
              <Button key={color} disabled variant={variant} color={color}>
                {capitalizeFirstLetter(color)}
              </Button>
            ))}
          </Stack>
        </div>
      ))}
    </ThemeProvider>
  );
}

Edit ColorButtons override disabled colors

Related