Search code examples
reactjsmaterial-uistyled-components

How to apply different styles for a reusable react button using mui


In my case button is a reusable component. It can be green with white text or white with green text and border. Is any better mui approach how to handle it?

Page:

   <MainButton title="Login" />
   <MainButton
      title="Register"
      additionalStyles={{         // add other styles 
      backgroundColor: "#e5f3fd",
      color: "#33b864",
      border: `1px solid ${theme.palette.secondary.main}`,
      "&:hover": {
        backgroundColor: "rgba(46, 171, 92, 0.1)",
      },
      }}
      />

MainButton:

export const MainButton = ({ title, additionalStyles }: MainButtonProps) => {
  const theme = useTheme();

  return (
    <Button
      sx={{
        height: 40,
        bgcolor: theme.palette.secondary.main,
        color: "#ffffff",
        textTransform: "none",
        fontSize: 15,
        fontWeight: 600,
        borderRadius: 2,
        "&:hover": {
          bgcolor: "#2eab5c",
        },
        ...additionalStyles,
      }}
    >
      {title}
    </Button>
  );
};

Solution

  • Looks like a decent approach currently as it allows for flexibility and extendability in case you would like to add more styles in the future using the additionalStyles prop.

    If you know you will only ever have those two variants, though, you might want to bake those styles into the component, and have them switch on a prop. An example below, but this is not necessarily better, just another approach.

    export const MainButton = ({ title, variant }: MainButtonProps) => {
      const theme = useTheme();
    
      const defaultStyles = {
        height: 40,
        textTransform: "none",
        fontSize: 15,
        fontWeight: 600,
        borderRadius: 2,
      };
    
      const primaryStyles = {
        bgcolor: theme.palette.secondary.main,
        color: "#ffffff",
        "&:hover": {
          bgcolor: "#2eab5c",
        },
      };
    
      const secondaryStyles = {
        backgroundColor: "#e5f3fd",
        color: "#33b864",
        border: `1px solid ${theme.palette.secondary.main}`,
        "&:hover": {
          backgroundColor: "rgba(46, 171, 92, 0.1)",
        },
      };
    
      const styles = variant === 'secondary' ? { ...defaultStyles, ...secondaryStyles } : { ...defaultStyles, ...primaryStyles };
    
      return (
        <Button sx={styles}>
          {title}
        </Button>
      );
    };
    

    And then that would be called using the variant prop:

    <MainButton title="Login" />
    <MainButton title="Register" variant="secondary" />
    

    This demonstrates more clearly that there are two clearly defined variants.