1

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;
});
zeckdude
  • 15,877
  • 43
  • 139
  • 187
  • My answer [here](https://stackoverflow.com/questions/70140504/how-to-pass-a-custom-style-to-mui-v5-styled-component/70148511#70148511) contains an example of using a prop with the `styled` API. – Ryan Cogswell Jun 09 '22 at 01:54
  • Thanks for your reply @RyanCogswell! I have tried to implement what I interpreted to be the solution based on your other post, but it doesn't seem to work. Can you please help me determine what I'm still missing? I've updated my question with the code. – zeckdude Jun 09 '22 at 07:40
  • Please provide a code sandbox reproducing your problem. – Ryan Cogswell Jun 09 '22 at 11:47

0 Answers0