Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you pass custom props to Material-UI v5 `styled()` components?

For example, in styled-components you can do the following:

const Div = styled.div`
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};
`;

render(
  <section>
    <Div>Normal</Div>
    <Div primary>Primary</Div>
  </section>
);

Can you get the same result with Material-UI v5 styled utility without adding overrides to the global theme object like the example in the styled() docs?

like image 477
benmneb Avatar asked Aug 17 '21 09:08

benmneb


People also ask

How do you pass props in material UI styled?

To pass props to React Material UI styles, we can call the useStyle hook returned by makeStyles with the props object. In makeStyles , we can set the style properties that takes the props as a parameter and return the value we want. We call makeStyles with an object that has some class names as properties.

Can styled-components receive custom props?

The css prop is a convenient way to iterate on your components without settling on fixed component boundaries yet. It works on both normal HTML tags as well as components, and supports everything any styled component supports, including adapting based on props, theming and custom components.

Can I pass props to styled component?

To pass props to React components created with styled-components, we can interpolate functions into the string that creates the component. We create the ArrowStyled component with the styled. div tag. Then string that we pass into the tag has the rotate value set from a prop.

Can you use material UI with styled-components?

By default, MUI components come with Emotion as their style engine. If, however, you would like to use styled-components , you can configure your app by following the styled engine guide or starting with one of the example projects: Create React App with styled-components.

Is it possible to style a Mui component directly to props?

Enable to learn the contribution process. Based on MUI's documentation of the styled () utility, the theme is provided for styling directly attached to the component, but props are supposed to be handled only within the overridesResolver option.

What is the difference between SX prop and styled function?

It is guaranteed that it will produce the same output as the styled function coming from the style library for the same input. The sx prop, on the other hand, is a new way of styling your components, focused on fast customization. styled is a function, while sx is a prop of the MUI components.

What is shouldforwardprop in Mui?

It adds support for the the sx prop (can be skipped). It adds by default the shouldForwardProp option (that can be overridden), taking into account all props used internally in the MUI components: ownerState, theme, sx, and as. Component: The component that will be wrapped.

How are the styles injected into the Dom by material UI?

The styles injected into the DOM by Material UI rely on class names that all follow a standard pattern : [hash]-Mui [Component name]- [name of the slot]. In this case, the styles are applied with .css-ae2u5c-MuiSlider-thumb but you only really need to target the .MuiSlider-thumb, where Slider is the component and thumb is the slot.


Video Answer


3 Answers

Yes!

The most basic example of the above would look like this in MUI v5:

const Div = styled("div")(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));


render (
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);

However, as the React docs say:

The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.

So MUI gave us the shouldForwardProp option to tell MUI whether it "should forward the prop" to the root node or not. The above example would look like this using that prop:

const Div = styled("div", {
  shouldForwardProp: (prop) => prop !== "primary"
})(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));

render (
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);

Explanation

The second argument to the styled function is an options object, one of the things it accepts is shouldForwardProp, which as the docs say, "Indicates whether the prop should be forwarded to the Component". So to remove the unknown prop warning from the console, we tell it not to pass our custom prop to the DOM element with shouldForwardProp: (prop) => prop !== "primary". Now we destructure this prop in the function call that returns our custom styles, and use it in those styles like we would any other function.

If you want to use the global theme styles here as well, just destructure it along with your custom prop(s), ie ({ primary, otherProp, thirdProp, theme }).

Working codesandbox.

MUI v5 styled API docs

like image 169
benmneb Avatar answered Oct 20 '22 16:10

benmneb


Here is a fully-working MUI v5 TypeScript example where you can pass custom properties to a styled component:

import React from 'react';
import { Button, styled, Typography } from '@mui/material';

const PREFIX = 'NimbusButton';
const classes = {
    root: `${PREFIX}-root`,
    button: `${PREFIX}-button`
};

interface RootProps {
    textColor?: 'primary' | 'secondary';
    buttonTextColor?: 'primary' | 'secondary';
}

const Root = styled('div', {
    shouldForwardProp: (prop) => prop !== 'textColor' && prop !== 'buttonTextColor',
    name: 'MyThemeComponent',
    slot: 'Root'
})<RootProps>(({ theme, textColor, buttonTextColor }) => ({
    [`& .${classes.root}`]: {
        color: textColor ? theme.palette.primary.main : theme.palette.secondary.main
    },
    [`& .${classes.button}`]: {
        color: buttonTextColor ? theme.palette.primary.main : theme.palette.secondary.main
    }
}));

type OwnProps = {
    textColor: 'primary' | 'secondary';
    buttonTextColor: 'primary' | 'secondary';
    text?: string;
    buttonText: string;
};

const CustomStyledButton: React.FC<OwnProps> = (props) => {
    const { textColor, buttonTextColor, text, buttonText } = props;
    return (
        <Root className={classes.root} textColor={textColor} buttonTextColor={buttonTextColor}>
            {text && <Typography variant={'body1'}>{text}</Typography>}
            <Button className={classes.button}>{buttonText}</Button>
        </Root>
    );
};

export default CustomStyledButton;
like image 42
Jerry H. Avatar answered Oct 20 '22 16:10

Jerry H.


If you are using TypeScript, I use utility function for it, so I always type prop names correctly:

export const shouldForwardProp = <CustomProps extends Record<string, unknown>>(
  props: Array<keyof CustomProps>,
  prop: PropertyKey,
): boolean => !props.includes(prop as string);

const MyComponent = styled('div', {
  shouldForwardProp: (prop) => shouldForwardProp<MyComponentProps>(['isDisabled', 'bgColor'], prop),
})<MyComponentProps>(({ theme, isDisabled, size, bgColor }) => ({
...
like image 2
marko424 Avatar answered Oct 20 '22 17:10

marko424