How do I convert styling from makeStyles to new styled API in MUI 5?

1.9k Views Asked by At

I am trying to convert a MUI 4 component to use the new styled API after migrating to MUI 5 but I’m getting lost on how I can pass specific props to the styled API like I was able to do using makeStyles previously. Can someone help me out there?

This is the component as it was when using makeStyles in MUI 4:


import React from 'react';
import PropTypes from 'prop-types';
import MuiTypography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Colors from 'Colors/index';

const acceptedColors = [...Object.values(Colors.gray), Colors.white];

export const variantMapping = {
  '2xl': {
    element: 'h1',
    styles: {
      primary: {
        fontSize: 81,
        lineHeight: '120%',
        letterSpacing: '-2px',
      },
      secondary: {
        fontSize: 81,
        lineHeight: '120%',
        letterSpacing: 0,
      },
    },
  },
  xl: {
    element: 'h2',
    styles: {
      primary: {
        fontSize: 54,
        lineHeight: '120%',
        letterSpacing: '-1px',
      },
      secondary: {
        fontSize: 54,
        lineHeight: '120%',
        letterSpacing: 0,
      },
    },
  },
  lg: {
    element: 'h3',
    styles: {
      primary: {
        fontSize: 36,
        lineHeight: '120%',
        letterSpacing: '-0.75px',
      },
      secondary: {
        fontSize: 36,
        lineHeight: '120%',
        letterSpacing: 0,
      },
    },
  },
  md: {
    element: 'h4',
    styles: {
      primary: {
        fontSize: 24,
        lineHeight: '130%',
        letterSpacing: '-0.5px',
      },
      secondary: {
        fontSize: 24,
        lineHeight: '140%',
        letterSpacing: 0,
      },
    },
  },
  sm: {
    element: 'p',
    styles: {
      primary: {
        fontSize: 16,
        lineHeight: '140%',
        letterSpacing: 0,
      },
      secondary: {
        fontSize: 16,
        lineHeight: '140%',
        letterSpacing: 0,
      },
    },
  },
  xs: {
    element: 'h5',
    styles: {
      primary: {
        fontSize: 14,
        lineHeight: '140%',
        letterSpacing: 0,
      },
      secondary: {
        fontSize: 14,
        lineHeight: '140%',
        letterSpacing: 0,
      },
    },
  },
  '2xs': {
    element: 'h6',
    styles: {
      primary: {
        fontSize: 12,
        lineHeight: '140%',
        letterSpacing: 0,
      },
      secondary: {
        fontSize: 12,
        lineHeight: '140%',
        letterSpacing: 0,
      },
    },
  },
};

const useStyles = makeStyles(() => ({
  root: ({ variant, isBold, font, color }) => {
    const baseStyles = {
      fontWeight: isBold || font === 'secondary' ? 700 : 'normal',
      fontFamily: font === 'secondary' ? ['"Lora"', 'serif'].join(',') : ['"Karla"', 'sans-serif'].join(','),
    };

    // If an unsupported variant is supplied, default to the `sm` font variant
    if (!Object.keys(variantMapping).includes(variant)) {
      // eslint-disable-next-line no-param-reassign
      variant = 'sm';
    }

    const variantStyles = variantMapping[variant].styles[font];

    // If an unsupported color is supplied, default to the gray[500]
    let colorHexCode = color;
    if (!acceptedColors.includes(color)) {
      const { '500': gray500 } = Colors.gray;
      colorHexCode = gray500;
    }

    return { ...baseStyles, ...variantStyles, color: colorHexCode };
  },
}));

const Typography = React.forwardRef(function Typography(
  { children, variant, className, component, isBold, font, canWrap, color, ...props },
  ref,
) {
  const classes = useStyles({ variant, isBold, font, color });

  return (
    <MuiTypography
      {...props}
      classes={classes}
      component={component || variantMapping[variant].element}
      className={className}
      noWrap={!canWrap}
      ref={ref}
    >
      {children}
    </MuiTypography>
  );
});

Typography.propTypes = {
  children: PropTypes.node.isRequired,
  variant: PropTypes.oneOf(Object.keys(variantMapping)),
  component: PropTypes.string,
  className: PropTypes.string,
  isBold: PropTypes.bool,
  font: PropTypes.oneOf(['primary', 'secondary']),
  canWrap: PropTypes.bool,
  color: PropTypes.oneOf(acceptedColors),
};

Typography.defaultProps = {
  isBold: false,
  component: null,
  className: '',
  font: 'primary',
  variant: 'sm',
  canWrap: true,
  color: Colors.gray[500],
};

export default Typography;

This is my start at trying to pass the props to the styled component, but it doesn't seem to be getting any values for those. What am I still missing?

const StyledMuiTypography = styled(MuiTypography)(({ theme, isBold, font }) => {
  const baseStyles = {
    fontWeight: isBold || font === 'secondary' ? 700 : 'normal',
    fontFamily: font === 'secondary' ? ['"Lora"', 'serif'].join(',') : ['"Karla"', 'sans-serif'].join(','),
  };

  return baseStyles;
});
0

There are 0 best solutions below