How to create MUI variants using props as vars in typescript?

150 Views Asked by At

I want to create variants for the Mui Button, so I started using the method below (as described in this documentation):

export const MuiButton: {
  defaultProps?: ComponentsProps['MuiButton'];
  styleOverrides?: ComponentsOverrides<Theme>['MuiButton'];
  variants?: ComponentsVariants['MuiButton'];
} = {
  variants: [
    {
      props: { variant: `outlined` },
      style: ({ theme }) => ({
        background: 'transparent',
        outline: `solid 0.1em`,
        ':hover': {
          background: theme.palette.primary.main,
          outline: `solid 0.25em`,
          boxShadow: theme.shadows[5],
        },
        transition: theme.transitions.create(`all`, {
          duration: theme.transitions.duration.short,
        }),
      }),
    },
  ]
}

My problem is that I can only take the theme as parameters, so I'm currently creating a variant for every color, which is really long and create a hard reading code. For now I'm only at the first variant out of 3 and the code already makes like 90 lines :

declare module '@mui/material/Button' {
  interface ButtonPropsVariantOverrides {
    flat: true;
  }
}

export const MuiButton: {
  defaultProps?: ComponentsProps['MuiButton'];
  styleOverrides?: ComponentsOverrides<Theme>['MuiButton'];
  variants?: ComponentsVariants['MuiButton'];
} = {
  defaultProps: {
    variant: 'outlined',
  },
  styleOverrides: {
    root: ({ theme }) => ({
      borderRadius: theme.shape.borderRadius,
      padding: theme.spacing(1, 2),
    }),
  },
  variants: [
    // flat
    {
      props: { variant: `flat` },
      style: ({ theme }) => ({
        background: 'transparent',
        outline: `solid 0.1em`,
        ':hover': {
          background: theme.palette.primary.main,
          outline: `solid 0.25em`,
          boxShadow: theme.shadows[5],
        },
        transition: theme.transitions.create(`all`, {
          duration: theme.transitions.duration.short,
        }),
      }),
    },
    {
      props: { variant: `flat`, color: `error` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.error.main,
        ':hover': {
          background: theme.palette.error.main,
          outlineColor: theme.palette.error.main,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `info` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.info.main,
        ':hover': {
          background: theme.palette.info.main,
          outlineColor: theme.palette.info.main,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `inherit` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.text.primary,
        ':hover': {
          background: theme.palette.text.primary,
          outlineColor: theme.palette.text.primary,
          color: theme.palette.background.paper,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `primary` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.primary.main,
        ':hover': {
          background: theme.palette.primary.main,
          outlineColor: theme.palette.primary.main,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `secondary` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.secondary.main,
        ':hover': {
          background: theme.palette.secondary.main,
          outlineColor: theme.palette.secondary.main,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `success` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.success.main,
        ':hover': {
          background: theme.palette.success.main,
          outlineColor: theme.palette.success.main,
        },
      }),
    },
    {
      props: { variant: `flat`, color: `warning` },
      style: ({ theme }) => ({
        outlineColor: theme.palette.warning.main,
        ':hover': {
          background: theme.palette.warning.main,
          outlineColor: theme.palette.warning.main,
        },
      }),
    },
  ]
}

Is there a method (maybe using the styled() function) to take the props as arguments so I can take the color directly without needing a block for each variant?

I hope I well described my problem as it's my first post

I tried using the styled() function but I didn't understand how to use it, maybe it's what I need but then how does it works? When I try to use it the page just stop working and I don't know why (console doesn't give anything)

0

There are 0 best solutions below